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

时间:2015-09-01 15:20:27

标签: java lambda java-8 java-stream

我有文件路径列表:。

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

54指的是文件ID

然后我获得Set String个{I}} ID,我的应用程序可以按如下方式处理:

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

如何使用Java 8 lambdas filter filePathsacceptedIds中不包含filePaths集合集中包含的任何可接受ID的所有元素。

换句话说,我希望仅在acceptedIds中保留filePaths.stream().filter(...).collect(Collectors.toList()); 集合中包含ID的路径。例如,54不在上面的列表中,因此被删除。

<?PHP include "var/www/public_html/myfile.php";

4 个答案:

答案 0 :(得分:24)

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

n

如果完成了相反的方法,在路径中搜索每个filePaths.stream() .filter(p -> acceptedIds.contains(p.getParent().getFileName().toString())) .collect(Collectors.toList()); (如在其他答案中),每个过滤器都是acceptedIds,其中O(m*k)是{的数量{ {1}}和m是平均路径长度,总体acceptedIds,即使是中等规模的集合也会表现很差。

答案 1 :(得分:3)

你可以写:

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

这会过滤每个路径,使得acceptedIds中至少有一个包含在路径的字符串表示中。您可能希望在此处实现比contains更好的功能,具体取决于您的用例(例如,匹配文件名的开头)。

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

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

答案 2 :(得分: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;
}

答案 3 :(得分:0)

如果您的文件名结构是常量,我首先使用正则表达式提取数字,然后检查它是否属于所需的ID。

<div class="color-swatch" 
     ng-if="quickOrderItem.colorNumber && 
           !quickOrderItem.isCustomColor && 
            filteredColors.length > 0" 
     ng-init="filteredColors = quickOrderItem.selectedSku.colorsArr | filterArrayOfObjects:quickOrderItem.colorNumber:'name':'colorNum'| limitTo:1" 
     ng-repeat="color in filteredColors">
</div>