使用java 8迭代和过滤两个列表

我想迭代两个列表并获得新的过滤列表,其中的值将不会出现在第二个列表中。 有人可以帮忙吗?

我有两个列表 – 一个是字符串列表,另一个是MyClass对象列表。

 List list1; List list2; MyClass { MyClass(String val) { this.str = val; } String str; ... ... } 

我希望基于 – >检查第二个列表中的元素(abc)的字符串列表,其值不在list1

 List list1 = Arrays.asList("abc", "xyz", "lmn"); List list2 = new ArrayList(); MyClass obj = new MyClass("abc"); list2.add(obj); obj = new MyClass("xyz"); list2.add(obj); 

现在我想要新的过滤列表 – >将有值=>“lmn”。 即list2不存在的值,其元素在list1

 // produce the filter set by streaming the items from list 2 // assume list2 has elements of type MyClass where getStr gets the // string that might appear in list1 Set unavailableItems = list2.stream() .map(MyClass::getStr) .collect(Collectors.toSet()); // stream the list and use the set to filter it List unavailable = list1.stream() .filter(e -> unavailableItems.contains(e)) .collect(Collectors.toList()); 

使用流来实现它很容易阅读:

 Predicate notIn2 = s -> ! list2.stream().anyMatch(mc -> s.equals(mc.str)); List list3 = list1.stream().filter(notIn2).collect(Collectors.toList()); 

最后,我得到了以下方式实现 –

 List unavailable = list1.stream() .filter(e -> (list2.stream() .filter(d -> d.getStr().equals(e)) .count())<1) .collect(Collectors.toList()); 

但这也是按预期工作的。 请告诉我这有效吗? 如果有人有其他办法做同样的事情?

如果您流式传输第一个列表并使用基于第二个包含的filter…

 list1.stream() .filter(item -> !list2.contains(item)) 

接下来的问题是,您将在此流式操作结束时添加哪些代码,以便将结果进一步处理给您。

此外,list.contains非常慢,因此使用集合会更好。

但是如果你正在使用集合,你可能会发现一些更简单的操作来处理这个问题,比如removeAll

 Set list1 = ...; Set list2 = ...; Set target = new Set(); target.addAll(list1); target.removeAll(list2); 

鉴于我们不知道您将如何使用它,因此无法建议采用哪种方法。

一个简单的方法是list1中的foreach并检查项目是否在list2中,如果没有添加到list3中。

 outer: for(String s : list1) { for(MyClass c : list2) if(c.getStr().equals(s)) continue outer; filteredList.add(c); } 

如果您发现继续标记混淆,请在布尔返回函数中提取内部循环。 您还可以替换lambda流迭代器的经典foreach。

 public static boolean isInList(ArrayList list, String s) { list2.stream().foreach((o)-> { if(o.getStr().equals(s)) { return true; } }); return false; } list1.stream().foreach((s) -> { if(!isInList(list2, s)) { list3.add(s); } }); 

但它真的看起来更加垃圾/污染,对我的眼睛来说是不必要的。

此外,您的类中的String str没有公共定义,这就是为什么我在两个示例中都使用“getStr()”方法,假设您的类遵循java bean模型并包含getStr()方法。

请参阅下文,欢迎任何人对以下代码的反馈。

两个数组之间不常见:

 List l3 =list1.stream().filter(x -> !list2.contains(x)).collect(Collectors.toList()); 

两个数组之间通用:

 List l3 =list1.stream().filter(x -> list2.contains(x)).collect(Collectors.toList()); 
 list1 = list1.stream().filter(str1-> list2.stream().map(x->x.getStr()).collect(Collectors.toSet()) .contains(str1)).collect(Collectors.toList()); 

这可能更有效。

如果你有id的类,你想按id过滤

line1:你mape所有的id

line2:过滤地图中不存在的内容

 Set mapId = entityResponse.getEntities().stream().map(Entity::getId).collect(Collectors.toSet()); List entityNotExist = entityValues.stream().filter(n -> !mapId.contains(n.getId())).map(DTOEntity::getId).collect(Collectors.toList());