我可能错了,但对我来说,我们可以为一个对象覆盖 equals,这样你就可以认为它们有意义地相等。映射中的所有条目都有不同的键,集合中的所有条目都有不同的值(没有意义地等于)
但是当使用 TreeMap 或 TreeSet 时,您可以提供一个比较器。我注意到,当提供比较器时,对象的 equals 方法被绕过,当比较器返回 0 时,两个对象被认为是相等的。因此,我们有 2 个对象,但在映射键集或集合中,只保留了一个。
我想知道是否有可能使用排序集合来区分两个不同的实例。
这是一个简单的示例:
public static void main(String[] args) {
TreeSet<String> set = new TreeSet<String>();
String s1 = new String("toto");
String s2 = new String("toto");
System.out.println(s1 == s2);
set.add(s1);
set.add(s2);
System.out.println(set.size());
}
请注意,使用 new String("xxx") 绕过了字符串池的使用,因此 s1 != s2。我想知道如何实现一个比较器,以便设置大小为 2 而不是 1。
主要问题是:对于相同字符串值的两个不同实例,我如何在比较器中返回一些东西!= 0?
请注意,我希望该比较器遵守规则:
比较它的两个参数的顺序。返回负整数、零或正整数,因为第一个参数小于、等于或大于第二个。实现者必须确保所有 x 和 y 的 sgn(compare(x, y)) == -sgn(compare(y, x))。(这意味着当且仅当 compare(y, x) 抛出异常时 compare(x, y) 必须抛出异常。)
实现者还必须确保关系是可传递的: ((compare(x, y)>0) && (compare(y, z)>0)) 意味着 compare(x, z)>0。
最后,实现者必须确保 compare(x, y)==0 意味着所有 z 的 sgn(compare(x, z))==sgn(compare(y, z))。
通常是这样,但并不严格要求 (compare(x, y)==0) == (x.equals(y))。一般来说,任何违反此条件的比较器都应清楚地表明这一事实。推荐的语言是“注意:这个比较器强加了与等于不一致的排序。”
我可以使用以下技巧:
public int compare(String s1,String s2) {
if s1.equals(s2) { return -1 }
...
}
它似乎工作正常,但由于 compare(s1,s2) != -compare(s2,s1) 没有遵守规则
那么这个问题有什么优雅的解决方案吗?
编辑:对于那些想知道我为什么问这样的事情的人。这更多是出于好奇,而不是任何现实生活中的问题。
但我已经遇到过这样的情况,虽然关于这个问题的解决方案:
想象一下你有:
class Label {
String label;
}
对于每个标签,您都有一个关联的字符串值。现在,如果你想要一个地图,标签-> 值怎么办。但是现在,如果您希望能够拥有与地图键相同的两倍标签怎么办?Ex "label" (ref1) -> value1 "label" (ref2) -> value2 您可以实现 equals 以便两个不同的 Label 实例不相等 -> 我认为它适用于 HashMap。
但是,如果您希望能够按字母顺序对这些 Label 对象进行排序呢?您需要提供比较器或实现可比较。但是我们如何才能区分具有相同标签的 2 个标签呢?我们必须!compare(ref1,ref2) 不能返回 0。但它应该返回 -1 还是 1 ?我们可以比较内存地址或类似的东西来做出这样的决定,但我认为这在 Java 中是不可能的......