我正在用Java实现一个A*算法,我使用TreeSet作为保持打开列表排序的简单方法.如果你不熟悉A*,它基本上是一个从A到B获得最短路径的函数,而开放列表是Tiles根据它们与B的接近度排序的节点列表(在我的例子中).
我的对象实现了一个compareTo()排序函数,如下所示:
@Override
public int compareTo( Tile b )
{
return ( this.f< b.f) ? -1 : ( this.f> b.f) ? 1 : 0;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试将一些图块添加到打开列表时,我的问题出现了 - TreeSet似乎compareTo()用来检查对象是否已经存在,而不是equals().由于两个不同Tiles的f值可能具有相同的值,因此TreeSet认为该对象已存在于列表中并且不会添加它.
根据文档(或至少,我如何阅读它),它应该使用equals:
"如果指定的元素不存在,则将其添加到此集合.更正式地说,如果集合中不包含元素e2,则将指定的元素e添加到此集合中(e == null?e2 == null:e.equals( e2))." (强调我的).
我怎样才能获得TreeSet的使用equals()时调用add()或contains()和compareTo()排序?对于info,我的Tile类不会覆盖该equals()函数,因此它应该是默认值return a == b.
如果我不想用TreeSet做什么,那么我应该使用的正确集合是什么?
根据TreeSet文档,这是预期的行为:
请注意,如果要正确实现Set接口,则由set维护的排序(无论是否提供显式比较器)必须与equals一致.(有关与equals一致的精确定义,请参阅Comparable或Comparator.)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,通过这种方法被认为相等的元素是相等的.集合的行为即使其排序与equals不一致也是明确定义的; 它只是不遵守Set接口的一般合同.
你打电话或打电话时无法TreeSet使用.您最好的选择是通过比较属性以及其他任何属性关注来使您的方法保持一致.equalsaddcontainscompareToequalsfequals