2015-09-01 125 views
19

我有文件路徑列表:如何從基於另一個列表的lambda列表中刪除元素

List<Path> filePaths; //e.g. [src\test\resources\file\15\54\54_exampleFile.pdf] 

54以上是指文件ID

我則獲得String IDS我的應用程序可以處理如下,其中一個Set

Set<String> acceptedIds = connection.getAcceptedIDs(); //e.g. elements [64, 101, 33] 

我如何使用Java 8個lambda表達式來filterfilePaths中的所有元素不包含acceptedIds收藏集中包含的任何可接受的ID。

換句話說,我想保留在filePaths只有ID爲acceptedIds設置的路徑。例如,54不在上面的列表中,因此被刪除。

filePaths.stream().filter(...).collect(Collectors.toList()); 
+1

我們可以依靠使用ID命名的直接父目錄嗎? – Bohemian

+4

filePaths.removeIf(p - >!acceptedIds.contains(p.getPath()) –

回答

22

最有效的方法是從路徑中提取的ID,然後嘗試找到它的設置,使得每個濾波器在固定時間內執行,即O(1)給人一種整體O(n)其中n是路徑數:

filePaths.stream() 
    .filter(p -> acceptedIds.contains(p.getParent().getFileName().toString())) 
    .collect(Collectors.toList()); 

如果反向的方式完成,其中每個acceptedIds在路徑搜索(如在其他的答案),每個濾波器是O(m*k),WHE macceptedIdsk的數目是平均路徑長度,給出總體O(n * m * k),即使是中等大小的集合,其性能也很差。

+0

我應該如何在提取時trim()'空格的ID? – user2781389

+0

空白在哪裏?在路徑中,例如''src \ test \ resources \ file \ 15 \ 54 \ 54_exampleFile.pdf「(目錄名是否爲」54「 - 帶空格),或存儲在」acceptedIds「中的值? – Bohemian

+0

存儲在'acceptedIds'中的值 – user2781389

3

你可以寫:

filePaths.stream() 
     .filter(p -> acceptedIds.stream().anyMatch(id -> p.toString().contains(id))) 
     .collect(toList()); 

這種過濾使得acceptedIds的至少一個包含在路徑的字符串表示的每個路徑。您可能想要在此處實現比contains更好的一些內容,具體取決於您的用例(例如,匹配文件名的開頭)。

anyMatch是一個操作,用於確定至少有一個元素是否與給定的謂詞匹配。

請注意,這個答案沒有做出任何有關濾除元素的路徑的假設。如果你可以放心地說,在每個路徑中,父目錄都是用id命名的,出於性能的原因,你一定要用@Bohemian的答案。

+1

'p.toString()。contains(id)'暗示''54「.contains(」4「)'或''543」 .contains(「4」)'我懷疑這與OP的意圖是否相符。 – Holger

+0

@Holger我同意,這就是爲什麼我說他可能想要更好地實現一些東西(比如匹配文件名的開頭)。 – Tunaki

1

像這樣:

List removeMissing(List l1, List l2) { 
    List ret = l1.stream() 
     .filter(o -> l2.contains(o)) //Keep if object o satisfies the condition "l2 contains a reference to this object" 
     .collect(Collectors.toList()); 
    return ret; 
} 
0

如果你的文件名結構是不變的,我會首先使用正則表達式來提取數字,然後檢查它是否在所需的ID中。

final Set<String> acceptedIds = ... 
// Matches the number of the file, concluded with the underscore 
final Pattern extractor = Pattern.compile("\.*(?<number>\d+)_") 
filePaths.stream().filter(path -> { 
    final Matcher m = extractor 
     .matcher(path.getFileName().toString()); 
    m.find(); 
    return acceptedIds.contains(m.group("number")); 
}) 
... 
相關問題