Java 8中两个列表对象的交集

时间:2018-12-16 17:58:19

标签: java arraylist java-8 java-stream intersect

java 8中两个List对象的交集。有人可以告诉我我在做什么错吗?

List<Student> originalStudent = new ArrayList<>();
List<Student> newStudent = new ArrayList<>();

List<Student> intersectListStudent = new LinkedList<>()

originalStudent.add(new Student("William", "Tyndale",1));
originalStudent.add(new Student("Jonathan", "Edwards",2));
originalStudent.add(new Student("Martin", "Luther"),3);

newStudent.add(new Student("Jonathan", "Edwards",2));
newStudent.add(new Student("James", "Tyndale",4));
newStudent.add(new Student("Roger", "Moore",5));


originalStudent.forEach(n ->
        newStudent.stream()
                .filter(db -> !n.getName().equals(db.getName()) &&
                        !n.getLastName().equals(db.getLastName()))
                    .forEach(student-> intersectListStudent .add(student)));

2 个答案:

答案 0 :(得分:7)

  

有人可以告诉我我在做什么错吗?

您违反了Side-effects原则,该原则概括地说,在通过管道执行操作时,流不应修改另一个集合。我尚未测试您的代码,但是,这不是您应该处理流的一种方式。


如何做得更好?

只需使用过滤器谓词中的List::contains即可摆脱唯一值。

List<Student> students = originalStudent.stream()
                                        .filter(newStudent::contains)
                                        .collect(Collectors.toList());

该解决方案(理解方法List::contains)基于使用Object::equals实现的相等性比较。因此,需要重写类Student中的相同方法。

编辑:请注意,自动覆盖Object::equals将使id等于计算。因此,相等将仅基于名称和姓氏。 (感谢@nullpointer)。

没有覆盖Object::equals吗?

您必须使用另一个filter和方法streamStream::anyMatch中进行比较,如果谓词合格,该方法将返回true

List<Student> students = originalStudent.stream()
              .filter(os -> newStudent.stream()                    // filter
                  .anyMatch(ns ->                                  // compare both
                       os.getName().equals(ns.getName() &&         // name
                       os.getLastName().equals(ns.getLastName()))) // last name
              .collect(Collectors.toList());

答案 1 :(得分:0)

您可以做的是从两个串联的列表SortedSet<Student>originalStudent构造一个newStudent。排序后的集合使用Comparator.comparing(Student::getName).thenComparing(Student::getLastName)作为其比较器。

Stream.concat(originalStudent.stream(), newStudent.stream())
    .collect(Collectors.toCollection(() -> new TreeSet<>(
        Comparator.comparing(Student::getFname)
            .thenComparing(Student::getLname))
    ))