如何从基于另一个列表的 lambda 列表中删除元素

2022-09-02 09:53:04

我有文件路径列表:。

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

54以上是指文件 ID

然后,我获取一个 ID,我的应用程序可以按如下方式处理:SetString

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

如何使用 Java 8 lambdas 来输出不包含集合集中包含的任何可接受 ID 的所有元素。filterfilePathsacceptedIds

换句话说,我只想保留具有集合中的ID的路径。例如,54 不在上面的列表中,因此被删除。filePathsacceptedIds

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

答案 1

最有效的方法是从路径中提取ID,然后尝试在Set中找到它,使每个过滤器以恒定时间执行,即给出一个整体,其中是路径数:O(1)O(n)n

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

如果采用相反的方法,其中在路径中搜索每个过滤器(如在其他答案中),则每个过滤器都是 ,其中是 数量并且是平均路径长度,给出一个整体 ,即使对于中等大小的集合,其性能也会非常差。acceptedIdsO(m*k)macceptedIdskO(n * m * k)


答案 2

你可以写:

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

这将筛选每个路径,以便路径的字符串表示形式中至少包含其中一个路径。您可能希望实现比这里更好的东西,具体取决于您的用例(例如,匹配文件名的开头)。acceptedIdscontains

anyMatch 是一个操作,用于确定是否至少有一个元素与给定谓词匹配。

请注意,此答案不会对筛选出元素的路径做出任何假设。如果可以肯定地说,在每个路径中,父目录都以id命名,那么出于性能原因,您绝对应该使用@Bohemian答案。


推荐