我需要按Integer值“level”对java对象集合进行排序。我还需要通过“title”确定此集合是否已包含对象。
我认为集合的最佳选择是TreeSet,它具有一组有序的唯一值。
我有一个带有“level”和“title属性的对象。它实现了可比性:
它重写了Equals方法(用于检查对象是否已经通过“title”包含在TreeSet中。
代码如下:
@Override
public boolean equals(Object arg0) {
Artifact obj = (Artifact) arg0;
if (this.getTitle().equals(obj.getTitle())) {
return true;
}
return false;
}
@Override
public int compareTo(Artifact aThat) {
final int BEFORE = -1;
final int EQUAL = 0;
final int AFTER = 1;
if (this == aThat) return EQUAL;
if (this.level < aThat.level) return BEFORE;
if (this.level > aThat.level) return AFTER;
assert this.equals(aThat) : "compareTo inconsistent with equals.";
return EQUAL;
}
当我尝试从可能具有重复值的arraylist中向列表添加值时。包含似乎不起作用,并且无论如何都将对象添加到TreeSet中。这是代码:
TreeSet<Artifact> subsetOfArtifacts = new TreeSet<Artifact>();
ArrayList<Artifact> allArtifacts = getArtifacts();
Iterator<Artifact> allArtifactsIter = allArtifacts.iterator();
while (allArtifactsIter.hasNext()) {
Artifact artifact = (Artifact) allArtifactsIter.next();
if (!subsetOfArtifacts.contains(artifact)) {
subsetOfArtifacts.add(artifact);
}
}
我希望理想情况下有一个按级别排序的所有唯一工件的列表。我该如何做到这一点?
答案 0 :(得分:3)
如果您覆盖equals()
,您也应该覆盖hashCode()
!否则,未定义集合(尤其是集合)的行为。您应该将此方法添加到您的班级:
@Override
public int hashCode() {
return title.hashCode();
}
接下来,您应该使用HashSet并使用Set sortedSet = new TreeSet(set);
进行排序。一旦你这样做,它应该都可以正常工作。
原因是HashTables依赖的事实是,如果两个对象是equal()
,那么他们的hashCode()
也相等。以下是hashCode()
hashCode的一般合约是:
- 每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终如一 返回相同的整数,前提是equals中没有使用的信息 对象的比较被修改。不需要保留该整数 从一个应用程序的执行到另一个执行的一致性 相同的申请。
- 如果两个对象根据equals(Object)方法相等,则必须对两个对象中的每一个调用hashCode方法 产生相同的整数结果。
- 如果两个对象根据equals(java.lang.Object)方法不相等,则不需要调用hashCode方法 两个对象中的每一个都必须产生不同的整数结果。 但是,程序员应该意识到产生了不同的 不等对象的整数结果可以提高性能 哈希表。
答案 1 :(得分:1)
你不仅需要compareTo来比较水平,还需要它来比较标题,因为equals比较了标题。
public int compareTo(Artifact aThat) {
final int BEFORE = -1;
final int EQUAL = 0;
final int AFTER = 1;
if ( this == aThat ) return EQUAL;
if (this.level < aThat.level) return BEFORE;
if (this.level > aThat.level) return AFTER;
return this.getTitle().compareTo(aThat.getTitle());
// assert this.equals(aThat) : "compareTo inconsistent with equals.";
// return EQUAL;
}
另外,正如波希米亚人所提到的,如果你要覆盖equals(),你应该覆盖hashCode(),但这不是你的TreeSet允许你添加重复项的原因。
答案 2 :(得分:0)
RTFM:D TreeSet的javadoc明确指出: “请注意,如果要正确实现Set接口,那么由一个集合维护的排序(无论是否提供显式比较器)必须与equals一致”
你的等于和比较器是不一致的。你需要添加的那个,然后你必须对它进行排序。
您可能需要为您的用例创建自己的实现
正如其他人所说:如果你改变了等号,总是改变哈希码。
2个相等的对象必须产生相同的哈希码。
答案 3 :(得分:0)
你的compareTo应首先检查级别,然后检查标题,如果你想先按级别然后按标题排序,只有当级别和标题相等时才返回相等。像这样:
@Override
public int compareTo(Artifact aThat)
{
final int BEFORE = -1;
final int EQUAL = 0;
final int AFTER = 1;
if ( this == aThat ) return EQUAL;
if( this.level < aThat.level ) return BEFORE;
if( this.level > aThat.level ) return AFTER;
int compare = this.getTitle().compareTo(aThat.getTitle());
if( compare != EQUAL ) return compare;
assert this.equals(aThat) : "compareTo inconsistent with equals.";
return EQUAL;
}
在张贴之前没有看到抢劫的答案。