[英]TreeSet add() returning false
我正在用Java实现一个A *算法,我使用TreeSet作为保持打开列表排序的简单方法。 如果你不熟悉A *,它基本上是一个从A到B获得最短路径的函数,而开放列表是基于它们与B的接近程度排序的节点列表(在我的例子中是Tiles
)。
我的对象实现了compareTo()
函数的排序,如下所示:
@Override
public int compareTo( Tile b )
{
return ( this.f< b.f) ? -1 : ( this.f> b.f) ? 1 : 0;
}
当我尝试将一些切片添加到打开列表时,我的问题出现了 - TreeSet似乎使用compareTo()
来检查对象是否已经存在,而不是equals()
。 由于两个不同的Tiles
可能具有相同的f
值,因此TreeSet认为该对象已存在于列表中并且不会添加它。
根据文档(或至少,我如何阅读它),它应该使用equals
:
“如果指定的元素不存在,则将其添加到此集合。更正式地说,如果集合中不包含元素e2,则将指定的元素e添加到此集合中(e == null?e2 == null:e.equals( e2)) 。“ (强调我的)。
在调用add()
或contains()
和compareTo()
进行排序时,如何让TreeSet使用equals()
? 对于info,我的Tile
类不会覆盖equals()
函数,所以它应该得到默认的return a == b
。
如果我不想用TreeSet做什么,那么我应该使用的正确集合是什么?
根据TreeSet文档,这是预期的行为:
请注意,如果要正确实现Set接口,则由set维护的排序(无论是否提供显式比较器)必须与equals一致。 (有关与equals一致的精确定义,请参阅Comparable或Comparator。)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,通过这种方法被认为相等的元素是相等的。 集合的行为即使其排序与equals不一致也是明确定义的; 它只是不遵守Set接口的一般合同。
调用add
或contains
时,无法让TreeSet
使用equals
。 最好的办法是通过比较f
属性以及其他属性equals
什么来使compareTo
方法与equals
一致。
我希望以下示例可以帮助SO用户。 我有类似的情况,我处理的方式是除了价值之外还使用id。 就我而言,价值指的是一个频率。
请注意使用'paddedText' - 如果你进行字符串比较,这是重要的3> 11。
public int compareTo(Object o) { String oText= o.getValue()+""; oText = String.format("%20s",oText).replace(' ', '0')+o.getName(); paddedText = this.value +""; paddedText=String.format("%20s",paddedText).replace(' ', '0') + this.name; return oText.compareTo(paddedText); }
这里的答案已经让我创造了这个。 我会把它留在这里因为似乎只有解决方案的要点。
@Override
public int compare(TileState lhs, TileState rhs) {
int compare = (lhs.getTaxicab + lhs.mMoves.size())
- (rhs.getTaxicab + rhs.mMoves.size());
if (compare == 0 && !lhs.equals(rhs)) return 1;
return compare;
}
只需在比较方法返回0时担心。
如果是这种情况并且equals将返回false,则返回0以外的任何值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.