krishna
krishna

Reputation: 499

List of custom object comparison using java8 (Streams)

I have two Lists containing objects of this class:

public class ClassObj {
    private Integer Id;
    private List<String> students;
}

I want to compare the objects in those two lists by students. I have to compare the lists and get data lijke below

  1. I need to create a new List containing those ClassObj objects which are present in list1 but not in list2
  2. I need to create a new List containing those ClassObj objects which are present in list2 but not in list1
  3. I need to create a new List containing those ClassObj objects which are present in both the lists using java8 streams

I tried with the below code

List<ClassObj> prevYearList = getPrevYearData(id);
List<ClassObj> currYearList = getCurrentYearData(id);

To find students who got TC (exists in list 1 but not in list2)

List<ClassObj> studentsGotTC = prevYearList.stream()
                    .filter(curr -> (currYearList.stream().filter(prev -> prev.getStudents().equals(curr.getStudents()))
                            .count()) < 1)
                    .collect(Collectors.toList());

To find new Admission (exists in list2 but not in list1)

List<ClassObj> newAdmission = currYearList.stream()
                    .filter(prev -> (prevYearList.stream()
                            .filter(curr -> prev.getStudents().equals(curr.getStudents())).count()) < 1)
                    .collect(Collectors.toList());

To find Students continuing in the school (exists in both list)

List<List<String>> studentsList = studentsGotTC.parallelStream()
                    .map(ClassObj::getStudents)
                    .collect(Collectors.toList());
List<ClassObj> existingStudents = prevYearList.stream()
                    .filter(e -> !studentsList.contains(e.getStudents()))
                    .collect(Collectors.toList());

It is returning me the results properly but i dont want to go through two streams and filter data, how to optimize the above code efficiently. i.e., by using single stream

Upvotes: 3

Views: 1855

Answers (2)

Naman
Naman

Reputation: 31878

You might not really need Streams at all for the task. How about this -

Set<ClassObj> uniqueStudentsOfPrevYear = new HashSet<>(prevYearList);
Set<ClassObj> uniqueStudentsOfCurrYear = new HashSet<>(currYearList);

List<ClassObj> studentsWithTC = new ArrayList<>(prevYearList);
studentsWithTC.removeIf(uniqueStudentsOfCurrYear::contains);

List<ClassObj> newAdmissions = new ArrayList<>(currYearList);
newAdmissions.removeIf(uniqueStudentsOfPrevYear::contains);

List<ClassObj> overlapping = new ArrayList<>(currYearList);
overlapping.retainAll(uniqueStudentsOfPrevYear);

Upvotes: 1

Harsh Mishra
Harsh Mishra

Reputation: 2135

For part 3 Common elements from both the List

Set<String> result = list.stream()
  .distinct()
  .filter(otherList::contains)
  .collect(Collectors.toSet());

After that, you can change the Set into a List.

For Part 1 And 2, you need to override the equals and hashcode method in ClassObj. So, you can use contains methods of the list. ArrayList's custom Contains method

List<ClassObj> studentsGotTC = prevYearList.stream()
                    .filter(prevYear-> currList.contains(prevYear))
                    .collect(Collectors.toList());

Upvotes: 0

Related Questions