Mat*_*man 18 java collections equals comparator
我有两个与我想要比较的相同类型对象的集合.在这种情况下,我想基于不考虑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.
}
}
Run Code Online (Sandbox Code Playgroud)
我想比较两个集合来断言,对于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;
}
Run Code Online (Sandbox Code Playgroud)
还有另一种方法吗?我是否错过了Commons Collections的明显方法?
我也在SO上发现了这个类似的问题虽然在那种情况下,我认为重写equals()
会更有意义.
与此非常相似的东西将在不久的将来(在撰写本文时)发布Apache Commons Collections.请参阅https://issues.apache.org/jira/browse/COLLECTIONS-446.
你可以使用Guava Equivalence类来解耦"比较"和"等价"的概念.您仍然需要编写比较方法(AFAIK Guava没有它)接受Equivalence子类而不是Comparator,但至少您的代码会更少混淆,您可以根据任何等价标准比较您的集合.
使用等价包装对象的集合(参见Equivalence中的wrap方法)类似于sharakan提出的基于Adapter的解决方案,但是等价实现将与适配器实现分离,允许您轻松使用多个等价标准.
您可以使用从版本 4 开始isEqualCollection
添加的新方法。CollectionUtils
该方法使用Equator
接口实现提供的外部比较机制。请检查这个javadocs:CollectionUtils.isEqualCollection(...)和Equator。
我不确定这种方式实际上更好,但它是“另一种方式”......
获取原始的两个集合,并创建包含每个基础对象的适配器的新集合。适配器应该具有.equals()
并.hashCode()
基于Name.calculateWeightedRank()
. 然后你可以使用正常的集合相等来比较适配器的集合。
* 编辑 *
使用 Eclipse 的标准 hashCode/equals 生成Adapter
. 您的代码只需对每个基本集合调用 AdaptCollection,然后调用 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;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
19139 次 |
最近记录: |