【问题标题】:Java TreeSet contains() gives false resultsJava TreeSet contains() 给出错误结果
【发布时间】:2011-05-17 19:02:18
【问题描述】:

我正在尝试用 java 编写一些数学代码。我想要做的是将 cyclotomic cosets 放入 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

有什么建议吗?

【问题讨论】:

  • Collection#contains设计提供false 结果(以及true)... scr

标签: java contains treeset


【解决方案1】:

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

来自API doc

请注意,由 a 维护的排序 设置(无论是否显式 比较器提供)必须是 与equals一致 正确实现 Set 接口。 (请参阅 Comparable 或 Comparator for a 符合的精确定义 等于。)之所以如此,是因为 Set 接口是根据定义的 等于操作,但是一个 TreeSet 实例执行所有元素 使用它的 compareTo 进行比较(或 compare) 方法,所以两个元素 被这种方法视为相等的是, 从集合的角度来看,相等。 集合的行为是明确定义的 即使它的顺序不一致 等于;它只是不服从 Set 接口的通用合约。

【讨论】:

  • 很难证明一致性。我更新了我上传的源文件,在那里我检查了前 1000 个陪集的 compareTo() 和 equals() 的一致性。到目前为止似乎是一致的。
  • @BlinK_:一致性要求 compareTo() 返回 0 iff equals() 返回 true。
【解决方案2】:

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

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

【讨论】:

    【解决方案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)并且搜索沿着树的错误路径前进。

    【讨论】:

    • 这是因为,正如 Tom Hawtin 所说,我没有通过 compareTo() 方法实现总排序。
    • 单元测试也会发现这个错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-16
    • 1970-01-01
    • 2011-11-15
    • 2019-02-06
    相关资源
    最近更新 更多