【问题标题】:Java lambda intersection two list and remove from resultJava lambda 交集两个列表并从结果中删除
【发布时间】:2018-08-30 12:30:44
【问题描述】:

我想将 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);
         }
     }
}

然后我想使用过滤器从 temp 中删除一些 Person,例如使用姓氏。

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

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

【问题讨论】:

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


    【解决方案1】:

    firstsecond 之间的交集:

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

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

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

    【讨论】:

      【解决方案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.containsKey(p.getName()))
          .filter(p -> !nameToSurname.get(p.getName()).contains(p.getSurname()))
          .collect(Collectors.toList());
      

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

      【讨论】:

        【解决方案3】:

        for-loops 都可能被压缩成两个Stream::filter 方法:

        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】:

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

          您可以使用Collection&lt;E&gt; 中的retainAll 方法。

          fist.retainAll(second);
          

          【讨论】:

            【解决方案5】:

            这里是方法参考和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 中编写代码。可能有一些编译器错误。

            【讨论】:

              猜你喜欢
              • 2015-10-19
              • 1970-01-01
              • 2018-05-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-10-04
              • 2020-06-30
              相关资源
              最近更新 更多