问题陈述
我有相同类型的对象,我想比较的两个集合。 在这种情况下,我想根据不计算入一个属性对它们进行比较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中一个明显的方法是什么?
有关
我也发现这个问题上的SO这是类似,虽然在这种情况下,我想最主要equals()
让人有点更有意义。
编辑
东西非常相似,这将是进入的一个版本的Apache Commons Collections中在不久的将来(在写这篇文章的时间)。 见https://issues.apache.org/jira/browse/COLLECTIONS-446 。
我不知道这种方式实际上是更好的,但它是“另一种方式” ......
把你原来的两个集合,然后创建一个包含每个基本对象的适配器新的。 适配器应有.equals()
和.hashCode()
为是基于实施Name.calculateWeightedRank()
然后你可以使用正常的收藏平等比较适配器的集合。
*编辑*
使用Eclipse标准的hashCode /等于一代的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;
}
}
您可以使用番石榴等价类,以分离的“比较”和“对等”的概念。 你仍然会写你的比较方法(据我所知番石榴没有它)接受一个等价的子类,而不是比较,但至少你的代码会少些混乱,你可以基于任何等价标准比较你的收藏。
使用equivance包裹对象的集合(见在等值包装方法 )是类似于sharakan提出了基于适配器的解决方案,但等价实施将从适配器实现脱钩,让您轻松使用多个等价标准。
您可以使用新的isEqualCollection
加入方法CollectionUtils
因为版本4.此方法使用提供的外部comparsion机制Equator
接口实现。 请检查此的javadoc: CollectionUtils.isEqualCollection(...)和赤道 。
编辑 :删除旧的答案。
你有被称为创建一个接口的另一种选择Weighted
可能看起来像这样的:
public interface Weighted {
int getWeightedRank();
}
然后让你的Name
的类实现此接口。 然后你可以改变你的方法是这样的:
public <T extends Weighted> boolean weightedEquals(Collection<T> col1, Collection<T> col2)
{
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 (i1.next().getWeightedRank() != i2.next().getWeightedRank()) {
return false;
}
}
return true;
}
然后,当你发现需要额外的类进行加权比较,你可以把它们放在你的收藏中,他们可以互相以及进行比较。 只是一个想法。