Reputation: 499
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
ClassObj
objects which are present in list1
but not in list2
ClassObj
objects which are present in list2
but not in list1
ClassObj
objects which are present in both the lists
using java8 streamsI 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
Reputation: 31878
You might not really need Stream
s 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
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