使用 Comparator 而不是 equals() 比较两个 Java 集合问题陈述问题相关

2022-09-02 22:21:30

问题陈述

我有两个相同类型对象的集合,我想进行比较。在本例中,我想根据不考虑对象的属性来比较它们。在我的示例中,我使用名称的排名集合,例如:equals()

public class Name {
    private String name;
    private int weightedRank;

    //getters & setters

    @Override
    public boolean equals(Object obj) {
        return this.name.equals(obj.name); //Naive implementation just to show
                                           //equals is based on the name field.
    }
}

我想比较这两个集合,以断言,对于每个集合中的位置,该位置的每个名称的值是相同的。我做了一些谷歌搜索,但没有在Commons Collections或任何其他API中找到合适的方法,所以我想出了以下内容:iweightedRank

public <T> boolean comparatorEquals(Collection<T> col1, Collection<T> col2,
        Comparator<T> c)
{
    if (col1 == null)
        return col2 == null;
    if (col2 == null) 
        return false;

    if (col1.size() != col2.size())
        return false;

    Iterator<T> i1 = col1.iterator(), i2 = col2.iterator();

    while(i1.hasNext() && i2.hasNext()) {
        if (c.compare(i1.next(), i2.next()) != 0) {
            return false;
        }
    }

    return true;
}

问题

有没有另一种方法可以做到这一点?我是否错过了共享资源收藏中明显的方法?

相关

我也在SO上发现了这个问题,这是类似的,尽管在这种情况下,我认为覆盖更有意义。equals()

编辑

与此非常相似的东西将在不久的将来(在撰写本文时)发布Apache Commons Collections。请参阅 https://issues.apache.org/jira/browse/COLLECTIONS-446


答案 1

您可以使用番石榴等价类来解耦“比较”和“等价”的概念。您仍然需要编写接受等效子类而不是比较器的比较方法(AFAIK Guava没有它),但至少您的代码会不那么混乱,并且您可以根据任何等效标准比较您的集合。

使用等价包装对象的集合(请参阅等效中的 wrap 方法)将类似于 sharakan 提出的基于适配器的解决方案,但等效实现将与适配器实现分离,从而允许您轻松使用多个等效条件。


答案 2

您可以使用自版本 4 以来添加到的新方法。该方法使用接口实现提供的外部比较机制。请检查此javadocs:CollectionUtils.isEqualCollection(...)EquatorisEqualCollectionCollectionUtilsEquator


推荐