Java TreeSet contains()给出错误的结果

时间:2010-11-30 10:28:09

标签: java contains treeset

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

例如:

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

有什么建议吗?

3 个答案:

答案 0 :(得分:4)

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

来自API doc

  

注意由a维护的排序   设置(无论是否明确   提供比较器)必须   如果是,则与等于一致   正确实现Set接口。   (参见Comparable或Comparator for a   精确定义符合   等于。)这是因为Set   接口是根据的定义的   等于操作,但是一个TreeSet   instance执行所有元素   比较使用compareTo(或   比较)方法,所以两个元素   被这种方法认为是平等的,   从集合的角度来看,是平等的。   集合的行为是明确定义的   即使它的排序不一致   与...平等它只是没有服从   Set接口的一般合约。

答案 1 :(得分:3)

Comparable中的Coset实施不提供总排序。

您似乎应该在value TreeSet上定义订单。在检查index之前或之后。

答案 2 :(得分: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)并且搜索沿着树的错误路径行进。