Java Lambda相交两个列表并从结果中删除

时间:2018-08-30 12:30:44

标签: java list lambda java-8 java-stream

我想将Java lambda表达式用于两个列表的交集,然后再与lambda表达式一起使用,我想从列表中删除。

示例:我有

List<Person> first = new ArrayList<Person>(); 
List<Person> second = new ArrayList<Person>(); 

假设两个列表都有一些Person对象。 我想将按名称过滤的两个列表的列表温度交集放入列表,例如:

List<Person> temp = new ArrayList<>();
for (Person one : first) {
     for (Person two : second) {                        
        if(one.getName.equals(two.getName)) {
                        temp.add(two);
         }
     }
}

然后我想使用过滤器(例如,使用姓氏)从临时人员中删除某些人。

for (Person tmp : temp) {
     for (Person one : first) {
        if (one.getSurname.equals(tmp.getSurname)) {
              temp.remove(tmp);
        }
     }
}

我想使用lambda表达式,我该怎么办?

5 个答案:

答案 0 :(得分:2)

您可以这样做

Map<String, Set<String>> nameToSurname = second.stream().collect(
        Collectors.groupingBy(Person::getName, 
            Collectors.mapping(Person::getSurname, Collectors.toSet())));
List<Person> temp = first.stream().filter(p -> nameToSurname.get(p.getName()) != null)
                .filter(p -> !nameToSurname.get(p.getName()).contains(p.getSurname()))
                .collect(Collectors.toList());

首先使用第二个列表创建一个从map到所有具有该名称的surnames的{​​{1}}。然后遍历第一个列表,对于每个人,通过将名称作为键来检查地图中是否有值。如果是,则检查姓氏是否与当前人的姓氏匹配。如果两个条件都满足,则将其收集到容器中。

答案 1 :(得分:1)

firstsecond之间的交点:

List<Person> intersection = first.stream()
        .filter(p1 -> second.stream().anyMatch(p2 -> p2.getName().equals(p1.getName())))
        .collect(Collectors.toList());

根据myList中的元素删除first中的元素:

first.stream()
    .filter(p1 -> myList.stream().anyMatch(p2 -> p1.getSurName().equals(p2.getSurName())))
    .forEach(myList::remove);

答案 2 :(得分:0)

Lambda并不总是最好的解决方案。

您可以使用retainAll中的Collection<E>方法。

fist.retainAll(second);

答案 3 :(得分:0)

两个for-loop可能被压缩为两个documentation方法:

List<Person> temp = second.stream()
    .filter(s ->  first.stream().anyMatch(f -> f.getName().equals(s.getName())))
    .filter(s -> !first.stream().anyMatch(f -> f.getSurame().equals(s.getSurame())))
    .collect(Collectors.toList());

答案 4 :(得分:0)

这是方法引用和not的解决方案。

second.stream()
     .filter(first.stream.map(Person::getName).collect(toSet())::contains)
     .filter(not(first.stream.map(Person::getSurname).collect(toSet())::contains))
     .collect(toList());

我没有在IDE中编写代码。可能会有一些编译器错误。