1

我正在尝试用java编写一些数学。我想要做的是将分圆陪集放到 TreeSet 中。陪集有一个索引和一组整数。如果集合具有相同的元素,则陪集等于其他陪集。如果集合不同,则陪集按其索引排序。

例如:

C1 = [1, 2, 4, 8]
C3 = [3, 6, 9, 12]
C9 = [3, 6, 9, 12]

C1 is less than C3
C3 is equal to C9

足够好的数学。我选择将陪集放到 TreeSet 中,因为我不需要重复的元素,我需要让它们按索引排序。

问题是即使 TreeSet.contains() 返回 false,我仍然可以在 TreeSet 中找到一个在使用 compareTo() 和 equals() 方法时相等的元素。

这是程序的实际打印输出:

cosets = [C0, C1, C3, C5, C7]
cosets.contains(C9) = false
C0.compareTo(C9) = -1, C0.equals(C9) = false
C1.compareTo(C9) = -1, C1.equals(C9) = false
C3.compareTo(C9) = 0, C3.equals(C9) = true
C5.compareTo(C9) = -1, C5.equals(C9) = false
C7.compareTo(C9) = -1, C7.equals(C9) = false

我附上下面的代码。我不想让代码变得更简单,因为我发现它有一些魔力。如果您在代码中将 MAGIC_INDEX值更改为 7 或更少,它就会开始工作。对我来说,这似乎是一个 JVM 错误。

http://2m.lt/files/Main.java

http://2m.lt/files/Coset.java

有什么建议么?

4

3 回答 3

4

您的compareTo()equals()方法不一致,TreeSet因此无法正确使用它们。

API 文档

请注意,如果要正确实现 Set 接口,集合维护的顺序(无论是否提供显式比较器)必须与 equals 一致。(参见 Comparable 或 Comparator 以了解与 equals 一致的精确定义。)这是因为 Set 接口是根据 equals 操作定义的,但 TreeSet 实例使用其 compareTo(或 compare)方法执行所有元素比较,所以两个从集合的角度来看,这种方法认为相等的元素是相等的。一个集合的行为是明确定义的,即使它的顺序与equals不一致;它只是不遵守 Set 接口的一般约定。

于 2010-11-30T10:35:35.033 回答
4

正如我经常说的,如果您的程序中有错误,请使用调试器。这很快就向我展示了你的问题。

TreeSet 是二叉树。在搜索时,它会根据您要查找的元素是在它正在检查的元素之前还是之后(或相同)来向下导航。如果您将以下内容添加到您的 compareTo()

System.out.println("Comparing, "+this+" to "+c);

它会打印出来

Comparing, C9 to C1
Comparing, C9 to C5
Comparing, C9 to C7

问题是 C9 在它不匹配的每个元素之后。因此,当它到达树上的 C5 时,您的 compareTo 表示它在它之后,而实际上它需要先查看(到达 C3)并且搜索沿着树的错误路径前进。

于 2010-11-30T11:02:41.730 回答
3

您的Comparable实现Coset不提供总排序。

看起来你应该在value TreeSet. 在检查之前或之后index

于 2010-11-30T10:39:26.443 回答