Java SortedSet+比较、一致性与平等()问题
-
19-09-2019 - |
题
我想有一个SortedSet的集(设置自己,在这种情况下,但不一定在一般的),这种通过收集的大小。这似乎违反了禁止以具有比较一致与平等()-即两个集合,也可以不等(由具有不同的元素),但比较的同样的价值(因为他们有同样数量的元素)。
名义上,我也可以把进入比较的方式进行排序设置平等的尺寸,但是使用这种不会利用这一点,并没有真的一个有用的+直观的方式比较集的大小相等的(至少在我的特定情况),因此这似乎是一种浪费。
这种情况下不一致似乎是一个问题吗?
解决方案
作为ChssPly76在评论中写道,你可以使用的hashCode决定在两个集合有相同的大小,但不相等的情况下的compareTo电话。这工作得很好,但在你有两个集合相同大小的罕见情况下,是不相等的,但有相同的hashCode。诚然,发生这种情况的几率非常小,但它是可以想象的。如果你想成为非常小心,而不是hashCode时,使用System.identityHashCode代替。这应该给你一个唯一的编号为每个集合,你不应该得到的碰撞。
在这一天结束,这让你有两个类别与配合尺寸的情况下,集合中按大小排序设置,任意排序的功能。如果这是你所需要的,这不是远远低于普通的比较会。如果需要排序是不同的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;
}
其他提示
SortedSet
接口扩展的核心 Set
因此应该符合合同中概述 Set
规范。
唯一可能的方式来实现,这是你的元素 equal()
法行为须符合你的 Comparator
-其中的原因是,核心 Set
工作的基础上平等而 SortedSet
工作的基础上进行比较。
例如, add()
方法中定义的一套核心指定的接口,你不能添加一个元件的设定如果已经有一个元素的 equal()
方法就会回真的有这个新的元素作为论据。好了, SortedSet
不使用 equal()
, 它使用 compareTo()
.所以如果你的 compareTo()
返回 false
你的元素将能加入,甚至如果 equals()
返回 true
, ,从而打破了 Set
合同。
所有这些都不是 实际 问题本身,但是。 SortedSet
行为始终是一致的,即使 compare()
vs equals()
不是。
这似乎违背了禁制 有比较一致 与equals() - 即,两个集合 可以是不相等的(由具有不同 元素),但比较相同 值(因为它们具有相同的 元素的数量)。
没有要求,无论是表示(在Javadoc)或暗示,即一个Comparator
是具有对象的实现boolean equals(Object)
一致。
请注意Comparable
和Comparator
是不同的接口使用不同的目的。 Comparable
用于定义一类“自然”顺序。在这种情况下,这将是equals
一个坏主意,并compateTo
不一致。相反,当要使用不同的顺序的一类的自然顺序一个Comparator
被使用。
编辑:下面是从的Javadoc的SortedSet完整的段落
请注意,通过一个保持的顺序 有序集合(无论是否明确 比较器提供的)必须 与equals一致,如果排序 一套是要正确地实现Set 接口。 (见可比 接口或比较器接口,用于 的一致的精确定义 与equals)。这是因为在 Set接口是来定义 equals操作,但有序 组执行所有元件比较 使用其的compareTo(或比较) 方法,所以两个元件是 认为等于通过该方法是,从 有序集合的角度来看, 等于。 有序集合的行为是 定义良好的,即使它的排序 与equals不一致;这只是 不服从的总承包合同 Set接口。
我强调最后一句。问题的关键是,这样的SortedSet的将工作,你很可能会想到,但某些操作的行为将不Set
规格完全一致......因为规范定义的equals
方法方面的行为。
所以,事实上,有是的一致性(我的错)所陈述的要求,但忽略它的后果并不像你想象的那样糟糕。当然,它是由决定是否应该这样做。据我估计,应该OK,只要你彻底注释代码,并确保该SortedSet的不“泄漏”。
不过,我也不清楚,对于收藏比较器,只有着眼于一个集合“大小”是去工作......从语义的角度。我的意思是,你真的想说,与(比如说)2种元素的所有集合都是平等的?这将意味着您所设定的永远只能包含任何给定大小的一个集合......
有没有理由为什么Comparator
应该返回相同的结果equals()
。事实上,引入了Comparator
API,因为equals()
是不够的:如果要排序的集合,你必须知道两个元素是否有或大或小
这是一点点奇怪的SortedSet作为标准API的一部分打破在Set接口中定义的合同,并使用比较器来定义平等代替equals方法,但是这是它是如何。
如果您的实际问题是,根据containted收藏大小排序集合的集合,你是用List,更好的,你可以使用Collections.sort(名单,比较>)进行排序;