使用比较器比较两个Java Collections而不是equals()

问题陈述

我有两个相同类型的对象的集合,我想比较.在这种情况下,我想根据不归因于对象的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.
    }
}

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

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

有另一种方法吗?我有没有想到从Commons Collections的一个明显的方法?

有关

我也发现了this question这是相似的,尽管在这种情况下,我正在考虑覆盖equals()有一点更有意义.

编辑

与此类似的事情将在不久的将来(在撰写本文时)发布为Apache Commons Collections.见https://issues.apache.org/jira/browse/COLLECTIONS-446.

最佳答案
我不知道这样做实际上更好,但它是“另一种方式”…

拿起原来的两个集合,并创建新的包含每个基础对象的适配器.适配器应该将.equals()和.hashCode()实现为基于Name.calculateWeightedRank().然后,您可以使用正常的集合等式来比较适配器的集合.

*编辑*

使用Eclipse的标准hashCode /等于生成适配器.你的代码只会在每个基础集合中调用adaptationCollection,然后将这两个结果称为List.equals().

public class Adapter {

    public List<Adapter> adaptCollection(List<Name> names) {
        List<Adapter> adapters = new ArrayList<Adapter>(names.size());

        for (Name name : names) {
            adapters.add(new Adapter(name));
        }

        return adapters;
    }


    private final int name;

    public Adapter(Name name) {
        this.name = name.getWeightedResult();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + name;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Adapter other = (Adapter) obj;
        if (name != other.name)
            return false;
        return true;
    }

}

转载注明原文:使用比较器比较两个Java Collections而不是equals() - 代码日志