2010-11-30 40 views
1

我想用java编写一点数学。我想要做的是将cyclotomic cosets添加到TreeSet。陪集有一个索引和一组整数。如果集合具有相同的元素,则陪集等于其他陪集。如果集合不同,则陪集按其索引排序。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,我仍然可以在使用compareTo()和equals()方法时在TreeSet中找到一个相等的元素。

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

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

有什么建议?

+1

`收集#包含`是**设计**给出'假'结果(以及'真正')...... scr – 2010-11-30 10:41:18

回答

3

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

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),并且搜索沿着树的错误路径。

4

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

API doc

注意,由 组(无论是否提供了明确的 比较器)保持的顺序必须是 与equals一致,如果它是 正确实现Set接口。 (参见可比或比较器,用于相一致的 精确的定义与 等于)。这是因为Set 接口在 等于操作定义的,但TreeSet 例如使用其的compareTo(执行所有元件 比较或 比较)的方法,所以通过这种方法认定两个元素 相等,从集合的观点看, 相等。 即使它的排序不一致 与等号,一个集合的行为是明确定义的 ;它只是不服从Set接口的 一般合同。

+0

很难证明一致性。我更新了我上传的源文件,在那里检查前1000个陪集的compareTo()和equals()的一致性。到目前为止,这似乎是一致的。 – dvim 2010-11-30 11:05:46

+0

@BlinK_:一致性要求compareTo()返回0 iff equals()返回true。 – 2010-11-30 11:09:35

3

您的ComparableCoset中的实现不提供总排序。

看起来你应该定义一个订单上的valueTreeSet。在检查index之前或之后。