如何配对两个列表中的项目

时间:2015-06-28 10:08:15

标签: java list lambda predicate

我有两个ClassA

列表
List<ClassA> list1;

List<ClassA> list2;

我想创建4个列表:

List<ClassA> matchedList1;

List<ClassA> matchedList2;

List<ClassA> unmatchedList1;

List<ClassA> unmatchedList2;

其中matchedList1matchedList2包含的订单项目具有相同的classA.name(唯一)

unmatchedList1unmatchedList2按顺序包含未配对的商品。

e.g。

list1 = name1, name2, name3
list2 = name4, name1, name3

matchedList1 = name1, name3 
matchedList2 = name1, name3 

unmatchedList1 = name2
unmatchedList2 = name4

是否有任何lambda表达式根据某个谓词来配对两个列表中的项目?

1 个答案:

答案 0 :(得分:2)

当您添加lambda标记时,我认为您可以使用Java-8解决方案。请注意,您的matchedList1unmatchedList1包含list1中的所有元素,因此您实际上需要根据{{list1中具有相同元素的谓词对list2进行分区。 1}}。这可以使用partitioningBy收集器完成:

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);

您可以完全以相同的方式创建matchedList2unmatchedList2

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);

请注意,此解决方案效率不高:其复杂度为O(list1.size()*list2.size())。如果您担心效率,最好在之前的两个列表中构建名称集。

或者,如果您的列表是按name字段预先排序的,则可以使用二进制搜索来加快过程:

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);