简体   繁体   English

如何比较两个数组列表与自定义比较器的相等性?

[英]How can I compare two array lists for equality with a custom comparator?

To be specific, I have two lists: 具体来说,我有两个清单:

List<SystemUserWithNameAndId> list1;
List<SystemUserWithNameAndId> list2;

I want to check if they contain the same system users and ordering is not an issue. 我想检查它们是否包含相同的系统用户,并且订购不是问题。 I tried to use a comparator to sort them first and then check if they're equal using the equals() method of lists. 我尝试先使用比较器对它们进行排序,然后使用列表的equals()方法检查它们是否相等。 But I don't want to override the equals method for SystemUserWithNameAndId and I was wondering if I could use the comparator I created for sorting or a similar one to check for equality without explicitly iterating through the lists after sorting. 但我不想覆盖SystemUserWithNameAndId的equals方法,我想知道我是否可以使用我为排序创建的比较器或类似的比较器来检查相等性,而不会在排序后显式迭代列表。

Comparator<SystemUserWithNameAndId> systemUserComparator = new Comparator<SystemUserWithNameAndId>()
    {

        @Override
        public int compare(SystemUserWithNameAndId systemUser1, SystemUserWithNameAndId systemUser2)
        {
            final int systemUserId1 = systemUser1.getSystemUserId();
            final int systemUserId2 = systemUser2.getSystemUserId();

            return systemUserId1 == systemUserId2 
                    ? 0
                    : systemUserId1 - systemUserId2;
        }
    };

    Collections.sort(systemUsers1, systemUserComparator);
    Collections.sort(systemUsers2, systemUserComparator);

    return systemUsers1.equals(systemUsers2);

Ideally, I want to be able to say, 理想情况下,我希望能够说,

CollectionUtils.isEqualCollections(systemUsers1, systemUsers2, someCustomComparator);

Just implement the method that iterates, and reuse it every time you need it: 只需实现迭代的方法,并在每次需要时重用它:

public static <T> boolean areEqualIgnoringOrder(List<T> list1, List<T> list2, Comparator<? super T> comparator) {

    // if not the same size, lists are not equal
    if (list1.size() != list2.size()) {
        return false;
    }

    // create sorted copies to avoid modifying the original lists
    List<T> copy1 = new ArrayList<>(list1);
    List<T> copy2 = new ArrayList<>(list2);

    Collections.sort(copy1, comparator);
    Collections.sort(copy2, comparator);

    // iterate through the elements and compare them one by one using
    // the provided comparator.
    Iterator<T> it1 = copy1.iterator();
    Iterator<T> it2 = copy2.iterator();
    while (it1.hasNext()) {
        T t1 = it1.next();
        T t2 = it2.next();
        if (comparator.compare(t1, t2) != 0) {
            // as soon as a difference is found, stop looping
            return false;
        }
    }
    return true;
}

Here's a Java 8 way of solving your problem. 这是解决问题的Java 8方法。 First make sure the lists are of equal length: 首先确保列表长度相等:

List<SystemUserWithNameAndId> list1 = ... ;
List<SystemUserWithNameAndId> list2 = ... ;

if (list1.size() != list2.size()) {
    return false;
}

Now build a Comparator using the new comparator utilities. 现在使用新的比较器实用程序构建Comparator。 The idea is that instead of writing custom logic for a comparator, most comparators do something like comparing two objects by extracting a key from them, and then comparing the keys. 我们的想法是,大多数比较器不是为比较器编写自定义逻辑,而是通过从两个对象中提取密钥来比较两个对象,然后比较密钥。 That's what this does. 这就是它的作用。

Comparator<SystemUserWithNameAndId> comp =
    Comparator.comparingInt(SystemUserWithNameAndId::getSystemUserId);

Sort the lists. 对列表进行排序。 Of course, you might want to make copies before sorting if you don't want your function to have the side effect of sorting its input. 当然,如果您不希望函数具有对其输入进行排序的副作用,您可能希望在排序之前制作副本。 If your input lists aren't random access (who uses LinkedList nowadays?) you might also want to copy them to ArrayList s to facilitate random access. 如果你的输入列表不是随机访问(谁现在使用LinkedList ?),你可能还想将它们复制到ArrayList以方便随机访问。

list1.sort(comp);
list2.sort(comp);

Run a stream over the indexes of the lists, calling the comparator on each pair. 在列表的索引上运行流,在每对上调用比较器。 The comparator returns 0 if the elements are equals according to this comparator. 如果元素根据此比较器等于,则比较器返回0。 If this is true for all pairs of elements, the lists are equal. 如果对于所有元素对都是如此,则列表是相等的。

return IntStream.range(0, list1.size())
    .allMatch(i -> comp.compare(list1.get(i), list2.get(i)) == 0);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM