Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intersection of Two Lists Objects in java 8

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)));
like image 813
Myjay1516 Avatar asked Dec 16 '18 17:12

Myjay1516


People also ask

How to get common elements from two lists in Java?

Here we will see how to get common elements from two lists we can even say the intersection of two lists using different ways. retainAll () method from the Collection interface is used to remove the common elements from two different lists. We even get the common elements from two lists using java 8 stream API distinct () method.

How many times can the intersection of two classes contain common elements?

The intersection should contain each common element only once. The order shouldn't matter, thus toSet is the most straightforward choice, but we can also use toList or another collector method.

What's new in Java 8?

Like many other things, this has become much easier thanks to the introduction of streams in Java 8. 2. Intersection of Two Lists of Strings Let's create two List s of String s with some intersection — both having some duplicated elements:

When are two instances of the same object equal in Java?

Then two instances are equal only if they refer to exactly the same object on the heap. For more information about the equals method, see our article on Java equals () and hashCode () Contracts. 4. Conclusion


2 Answers

Can some tell me what am I doing wrong?

You violate the Side-effects principle of java-stream 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());
like image 97
Nikolas Charalambidis Avatar answered Sep 21 '22 15:09

Nikolas Charalambidis


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))
    ))
like image 37
HPH Avatar answered Sep 22 '22 15:09

HPH