Java SortedSet+;比较器,与equals()问题的一致性

Java SortedSet+;比较器,与equals()问题的一致性,java,equals,comparator,sortedset,Java,Equals,Comparator,Sortedset,我希望有一个集合的SortedSet(在本例中,集合本身,但不一定是一般集合),它按集合大小进行排序。这似乎违反了将比较器与equals()保持一致的规定-即,两个集合可能不相等(通过具有不同的元素),但与相同的值进行比较(因为它们具有相同的元素数) 理论上,我也可以使用Comparator方法对大小相等的集合进行排序,但使用排序方法不会利用这一点,而且没有一种真正有用的+直观的方法来比较大小相等的集合(至少在我的特定情况下),因此这似乎是一种浪费 这种不一致的情况似乎是个问题吗?没有理由让比较

我希望有一个集合的SortedSet(在本例中,集合本身,但不一定是一般集合),它按集合大小进行排序。这似乎违反了将比较器与equals()保持一致的规定-即,两个集合可能不相等(通过具有不同的元素),但与相同的值进行比较(因为它们具有相同的元素数)

理论上,我也可以使用Comparator方法对大小相等的集合进行排序,但使用排序方法不会利用这一点,而且没有一种真正有用的+直观的方法来比较大小相等的集合(至少在我的特定情况下),因此这似乎是一种浪费


这种不一致的情况似乎是个问题吗?

没有理由让比较器返回与
equals()相同的结果。事实上,引入
比较器
API是因为
equals()
还不够:如果要对集合进行排序,必须知道两个元素是较小还是较大。

比较器
没有理由返回与
equals()
相同的结果。事实上,之所以引入
比较器
API,是因为
equals()
还不够:如果要对集合进行排序,必须知道两个元素的大小。

接口扩展了核心,因此应该符合
集合
规范中概述的契约

实现这一点的唯一可能方法是使元素的
equal()

例如,在核心集接口中定义的方法指定,如果已经有一个元素的
equal()
方法将以该新元素作为参数返回true,则不能将元素添加到集合中。好的,
SortedSet
不使用
equal()
,它使用
compareTo()
。因此,如果您的
compareTo()
返回
false
,那么即使
equals()
返回
true
,您的元素也将被添加,从而打破了
集合
契约

然而,这一切本身都不是一个实际的问题<代码>分类数据集
行为始终一致,即使
比较()
相等()
不一致。

接口扩展了核心,因此应符合
规范中概述的合同

实现这一点的唯一可能方法是使元素的
equal()

例如,在核心集接口中定义的方法指定,如果已经有一个元素的
equal()
方法将以该新元素作为参数返回true,则不能将元素添加到集合中。好的,
SortedSet
不使用
equal()
,它使用
compareTo()
。因此,如果您的
compareTo()
返回
false
,那么即使
equals()
返回
true
,您的元素也将被添加,从而打破了
集合
契约


然而,这一切本身都不是一个实际的问题
SortedSet
行为总是一致的,即使
compare()
equals()
不一致。

SortedSet作为标准API的一部分,打破了Set接口中定义的契约,使用比较器定义相等,而不是equals方法,这有点奇怪,但事实就是这样


如果您的实际问题是根据包含的集合的大小对集合进行排序,那么最好使用列表,可以使用集合进行排序

有点奇怪,SortedSet作为标准API的一部分打破了Set接口中定义的契约,使用比较器来定义相等,而不是equals方法,但事实就是这样


如果您的实际问题是根据包含的集合的大小对集合进行排序,那么最好使用列表,可以使用集合进行排序

正如ChssPly76在评论中所写,如果两个集合大小相同但不相等,则可以使用hashCode来决定compareTo调用。这很好,除非在罕见的情况下,您有两个大小相同的集合,它们不相等,但具有相同的哈希代码。诚然,发生这种情况的可能性很小,但这是可以想象的。如果您想非常小心,请使用System.identityHashCode代替hashCode。这将为每个集合提供一个唯一的编号,并且不会发生冲突

在一天结束时,这为您提供了按大小排序集合中集合的功能,对于大小匹配的两个集合,可以任意排序。如果这就是你所需要的,它不会比通常的比较慢很多。如果您需要不同JVM实例之间的顺序保持一致,那么这将不起作用,您必须以其他方式来完成

伪代码:

if (a.equals(b)) {
    return 0;
} else if (a.size() > b.size()) {
    return 1;
} else if (b.size() > a.size()) {
    return -1;
} else {
    return System.identityHashCode(a) > System.identityHashCode(b) ? 1 : -1;
}

正如ChssPly76在注释中所写的,在两个集合大小相同但不相等的情况下,可以使用hashCode来决定compareTo调用。这很好,除非在罕见的情况下,您有两个大小相同的集合,它们不相等,但具有相同的哈希代码。诚然,发生这种情况的可能性很小,但这是可以想象的。如果您想非常小心,请使用System.identityHashCode而不是hashCode