我正在做以下
class RuleObject implements Comparable{
@Override
public String toString() {
return "RuleObject [colIndex=" + colIndex + ", probability="
+ probability + ", rowIndex=" + rowIndex + ", rule=" + rule
+ "]";
}
String rule;
double probability;
int rowIndex;
int colIndex;
public RuleObject(String rule, double probability) {
this.rule = rule;
this.probability = probability;
}
@Override
public int compareTo(Object o) {
RuleObject ruleObj = (RuleObject)o;
System.out.println(ruleObj);
System.out.println("---------------");
System.out.println(this);
if(ruleObj.probability > probability)
return 1;
else if(ruleObj.probability < probability)
return -1;
else{
if(ruleObj.colIndex == this.colIndex && ruleObj.rowIndex == this.rowIndex && ruleObj.probability == this.probability && ruleObj.rule.equals(this.rule))
return 0;
}
return 1;
}
}
我有一个包含RuleObject元素的TreeSet。 我正在尝试执行以下操作:
System.out.println(sortedHeap.size());
RuleObject ruleObj = sortedHeap.first();
sortedHeap.remove(ruleObj);
System.out.println(sortedHeap.size());
我可以看到集合的大小保持不变。我无法理解它为什么不被删除。 同时在删除时我可以看到compareTo方法被调用。但它只需要3个对象,而在集合中则有8个对象。 感谢
答案 0 :(得分:4)
如polygenelubricants
所示,您必须在equals
上实施RuleObject
。
此外,您的comparator基本上已被破坏。它没有强加total ordering,即在某些情况下它会声称RuleObject
a
大于和小于另一个RuleObject
b
(例如,如果a.probability
== b.probability
和a.colIndex
!= b.colIndex
。)这会在树插入,遍历等过程中导致不必要的行为。
最后,compareTo
must also be consistent with equals
,即
C类的自然顺序是 据说与ifals一致 并且仅当(e1.compareTo((Object)e2) == 0)对于每个e1和e1具有与e1.equals((Object)e2)相同的布尔值 C类的e2。注意null不是 任何类的实例,和 e.compareTo(null)应抛出一个 尽管NullPointerException e.equals(null)返回false。
如果您不关心RuleObject
的订购,请使用HashSet
。
否则(即您希望以明确定义的优先顺序迭代TreeSet
),实施Comparable
以考虑所有感兴趣的字段,例如:
public int compareTo(Object o) {
RuleObject r = (RuleObject)o;
// assume no nulls for now, but you should eventually check
// also assume o is always of type RuleObject for now,
// but you should eventually check
return
priority < r.priority ? -1 :
priority > r.priority ? 1 :
colIndex < r.colIndex ? -1 :
colIndex > r.colIndex ? 1 :
rowIndex < r.rowIndex ? -1 :
rowIndex > r.rowIndex ? 1 : 0;
}
boolean equals(Object o) {
// Delegate to compareTo(); no code duplication, consistent.
return compareTo(o) == 0;
}
答案 1 :(得分:4)
查看remove
的规范:
从该集合中删除指定的元素(如果存在)。更正式地,如果此集合包含此类元素,则删除
e
元素(o==null ? e==null : o.equals(e))
。
您的问题是RuleObject
没有@Override equals(Object other)
。你需要这样做,当然,你还需要@Override hashCode()
。
此外,调用compareTo
的次数少于元素数量的原因是因为它应该是O(log N)
操作;这是使用TreeSet
的全部目的。如果您有1024个元素,则可以期望compareTo
被调用不超过10次。
弗拉德指出,你的比较器坏了。具体来说,最后一个语句return 1;
打破了它。您应该扩展相等的probability
大小写以返回-1,0,+ 1,具体取决于其他字段。
答案 2 :(得分:0)
如果您想要Just Work™,请尝试Apache的CompareToBuilder,HashCodeBuilder和EqualsBuilder。我已经提供了从下面开始的示例代码。你当然不必采取这种方式,但我认为你会发现它简化了事情。注意不同功能之间的一致模式。
public int compareTo(Object o) {
RuleObject ruleObj = (RuleObject) o;
return new CompareToBuilder()
.append(this.probability, ruleObj.probability)
.append(this.colIndex, ruleObj.colIndex)
.append(this.rowIndex, ruleObj.rowIndex)
.append(this.rule, ruleObj.rule)
.toComparison();
}
public int hashCode() {
// You should customize the hard-coded numbers, as described in the docs.
return new HashCodeBuilder(17, 37).
append(probability).
append(colIndex).
append(rowIndex).
append(rule).
toHashCode();
}
public boolean equals(Object obj) {
if (obj == null) { return false; }
if (obj == this) { return true; }
if (obj.getClass() != getClass()) {
return false;
}
RuleObject rhs = (RuleObject) obj;
return new EqualsBuilder()
.append(probability, rhs.probability)
.append(colIndex, rhs.colIndex)
.append(colIndex, rhs.colIndex)
.append(rule, rhs.rule)
.isEquals();
}