我已经阅读了很多关于TreeSet,Comparable / Comparator Interfaces,equals,compareTo,compare methods的帖子,我知道API说你必须订购#34;与equals"或者可能发生奇怪的事情。
但在我的情况下,我认为这是一个相当普遍的情况,我确实需要一个TreeSet排序,这与#equ;"不一致。
假设我们正在进行某种启发式搜索,并且我们正在从根(初始)状态开始扩展(或生成)新状态。我们将新的(扩展/生成)状态放入TreeSet中,我们通常称之为打开列表。我们想使用TreeSet容器,因为我们不希望在打开的列表中出现重复的状态。
生成/扩展的每个状态都由成本函数评估,并给出一个启发式值,显示状态的质量。我们想要按此值排序的TreeSet(打开列表)。我们希望在TreeSet的顶部具有最佳状态(具有最佳成本值)。
现在问题来了。为了适应成本值的排序,我们需要为TreeSet提供一个比较成本值的比较器。但是,两个不同的状态可以具有相同的成本/启发式值。我希望在我的公开名单上都有这两种状态,因为它们不等于#34;。但比较器需要从比较方法返回0,因为它们具有相同的成本值。因此,具有相同成本值的不同状态将不会插入到列表中。
我想举一个简单的例子来说明这一点更容易理解。 假设我们的状态是显示二进制数据的字符串,而成本函数计算字符串中的" 1" s。
让我们说这些是生成的状态及其各自的成本值。
No State Cost
1 01001001 3
2 01101001 4
3 10001001 3
4 01001111 5
正如您所看到的,这四种状态都不同。他们不等于"。但即使状态1和状态-3不同,它们也具有相同的成本值" 3"。因此,当我们按成本订购TreeSet时,state-3将不会添加到TreeSet中,因为已经存在具有相同成本值的元素。但我们需要将该状态添加到列表中,因为它是完全有效的,不同的新状态。
我该如何克服这个问题?
感谢。
答案 0 :(得分:4)
你需要的只是一个做两件事的比较器:
这是一种lexicographic ordering,它与equals()
完全一致。 (因为如果equals()
返回true,比较器将返回0。)
完全抛弃:根据您的具体使用情况,使用PriorityQueue
而不是TreeSet
可能会更好。然后,您不必担心具有相同优先级的多个元素。
答案 1 :(得分:1)
“与equals一致”的含义仅表示对于彼此相等的两个对象,比较器应返回0,或者:
obj1.equals(obj2)
应与comparator.compare(obj1, obj2) == 0
;
但是你可以自由地使用自己的比较器,只要比较器为相同的状态返回0,就可以在高成本之前降低成本。