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)));
答案 0 :(得分:7)
有人可以告诉我我在做什么错吗?
您违反了Side-effects的java-stream原则,该原则概括地说,在通过管道执行操作时,流不应修改另一个集合。我尚未测试您的代码,但是,这不是您应该处理流的一种方式。
如何做得更好?
只需使用过滤器谓词中的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
和方法stream
在Stream::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))
))