Intersection of Two Lists Objects in java 8
Asked Answered
D

2

5

An intersection of Two Lists Objects in java 8. Can some tell me what am I doing wrong?

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)));
Dump answered 16/12, 2018 at 17:58 Comment(2)
what is the output that you're expecting? what is that you think is wrong? that's not self explanatory by the waySpearhead
Since a List can contain the same element multiple times, when you intersect the lists, if A has element x three times, and B has element x twice times, how many times do you expect the answer in the final list? 3? 2? 1? This will determine which of these approaches works.Polytechnic
E
15

Can some tell me what am I doing wrong?

You violate the Side-effects principle of which in a nutshell says that a stream shouldn't modify another collection while performing the actions through the pipelines. I haven't tested your code, however, this is not a way you should treat streams.


How to do it better?

Simply use the List::contains in the filter's predicate to get rid of the unique values.

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

This solution (understand the method List::contains) is based on the implemented equality comparison using Object::equals. Hence, there is needed to override the very same method in the class Student.

Edit: Please, be aware that that automatically overriding the Object::equals will mind the id to the equality computation. Therefore the equality will be based on the name and surname only. (thanks to @nullpointer).

Without the Object::equals overridden?

You have to perform the comparison in the filter using another stream and the method Stream::anyMatch which returns true if the predicate is qualified.

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());
Eyestalk answered 16/12, 2018 at 18:50 Comment(4)
this would definitely need an object comparison. also the fact that is the last attribute value changes in the two sample lists provided, the output would vary here from what is expected in the question.Spearhead
I meant, if I change originalStudent.add(new Student("Jonathan", "Edwards",2)); to originalStudent.add(new Student("Jonathan", "Edwards",7));, you first code block wouldn't provide same output as your latter suggestion.Spearhead
Plus one for the solution with anyMatch and collect :)Spearhead
@Myjay1516, why is this not the accepted answer? :/Hilaryhilbert
R
1

What you can do is construct a SortedSet<Student> from the two concatenated lists originalStudent and newStudent. The sorted set uses a Comparator.comparing(Student::getName).thenComparing(Student::getLastName) as its comparator.

Stream.concat(originalStudent.stream(), newStudent.stream())
    .collect(Collectors.toCollection(() -> new TreeSet<>(
        Comparator.comparing(Student::getFname)
            .thenComparing(Student::getLname))
    ))
Raker answered 17/12, 2018 at 20:0 Comment(1)
Works fine for me. Thank you!... Those who are working with list you have to convert treeset to list. new ArrayList<Student>(treeSetListVariable)Funchal

© 2022 - 2024 — McMap. All rights reserved.