Reputation: 15472
I have two lists of ClassA
List<ClassA> list1;
List<ClassA> list2;
I want to create 4 lists:
List<ClassA> matchedList1;
List<ClassA> matchedList2;
List<ClassA> unmatchedList1;
List<ClassA> unmatchedList2;
where matchedList1
and matchedList2
contain in order items with same classA.name
(unique)
unmatchedList1
and unmatchedList2
contain in order items that were not paired.
e.g.
list1 = name1, name2, name3
list2 = name4, name1, name3
matchedList1 = name1, name3
matchedList2 = name1, name3
unmatchedList1 = name2
unmatchedList2 = name4
is there any lambda expression to pair items from two lists according to some predicate?
Upvotes: 2
Views: 1714
Reputation: 100209
As you added the lambda
tag, I suppose that you are ok with Java-8 solution. Note that your matchedList1
and unmatchedList1
contain all the elements from the list1
, so you actually need to partition the list1
according to the predicate of having the same element in list2
. This can be done using the partitioningBy
collector:
Map<Boolean, List<ClassA>> map1 = list1.stream().collect(
Collectors.partitioningBy(e1 -> list2.stream().anyMatch(
e2 -> e1.name.equals(e2.name))));
List<ClassA> matchedList1 = map1.get(true);
List<ClassA> unmatchedList1 = map1.get(false);
You can create matchedList2
and unmatchedList2
exactly in the same way:
Map<Boolean, List<ClassA>> map2 = list2.stream().collect(
Collectors.partitioningBy(e2 -> list1.stream().anyMatch(
e1 -> e1.name.equals(e2.name))));
List<ClassA> matchedList2 = map2.get(true);
List<ClassA> unmatchedList2 = map2.get(false);
Note that this solution is not very efficient: its complexity is O(list1.size()*list2.size())
. If you worry about the efficiency, it's better to build the sets of the names in both lists before.
Alternatively if your lists are pre-sorted by the name
field, you can use the binary search to speedup the procedure:
Comparator<ClassA> comparator = Comparator.comparing(e -> e.name);
Map<Boolean, List<ClassA>> map1 = list1.stream().collect(
Collectors.partitioningBy(e1 -> Collections.binarySearch(list2, e1, comparator) >= 0));
List<ClassA> matchedList1 = map1.get(true);
List<ClassA> unmatchedList1 = map1.get(false);
Map<Boolean, List<ClassA>> map2 = list2.stream().collect(
Collectors.partitioningBy(e2 -> Collections.binarySearch(list1, e2, comparator) >= 0));
List<ClassA> matchedList2 = map2.get(true);
List<ClassA> unmatchedList2 = map2.get(false);
Upvotes: 2