2015-09-01 100 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")); 
}) 
... 
相关问题