我正在尝试用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()和compareTo()方法时是相等的。
这是程序的实际打印结果:
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
有什么建议吗?
发布于 2010-11-30 11:02:41
正如我经常说的,如果程序中有错误,请使用调试器。这很快就向我表明了你的问题。
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-30 10:35:35
您的compareTo()
和equals()
方法不一致,因此TreeSet
无法正确地使用它们。
来自API文档
请注意,如果要正确实现set接口,则由Set维护的排序(无论是否提供显式比较器)必须与equals一致。(与平等一致的精确定义见可比或比较器)。这是因为set接口是按照等于操作定义的,但是TreeSet实例使用它的compareTo (或compare)方法执行所有元素比较,因此从Set的角度来看,这个方法认为相等的两个元素是相等的。一个集合的行为是明确的,即使它的顺序与相等不一致;它只是没有遵守set接口的一般契约。
发布于 2010-11-30 10:39:26
您的Comparable
实现在Coset
中没有提供全面排序。
看起来您应该在value
TreeSet
上定义一个订单。无论是在检查index
之前还是之后。
https://stackoverflow.com/questions/4312653
复制相似问题