【问题标题】:Conventions used in Java documentationJava 文档中使用的约定
【发布时间】:2013-12-12 04:44:30
【问题描述】:

为什么TreeSetHashSetadd() 方法的Oracle Java API 文档指出:

只有在(e==null ? e2==null : e.equals(e2))的集合中没有e2时才添加元素e

但是,TreeSet 使用compareTo(),而HashSet 使用hashCode() 来确定相等性。两者都忽略了equals() 的值。我担心文档不准确,还是我对约定或算法的理解有问题?

【问题讨论】:

    标签: java hashset treeset


    【解决方案1】:

    您认为 TreeSet 文档不正确是正确的。

    您对 HashSet 的看法不正确,因为它确实使用了equals()hashCode() 用于相等性测试,仅用于快速搜索。

    【讨论】:

    • 如果 hashCode() 设置为总是返回相同的代码,那么 add() 的行为似乎依赖于 equals()。但是,如果我创建一个对象,其中 equals() 始终返回 'true' 并且不覆盖 hashCode() - 所以它对于不同的对象有所不同 - 然后 add() 将添加多个对象。因此 add() 的行为似乎比文档中所述的更复杂。正如路易斯所说,这些情况不在合同范围内,但我对实施很感兴趣(因为它没有按照它所说的那样做)——有人知道是否有规范规范吗?
    • @user3038094 - 我建议阅读 HashMap 的工作原理。那么你就会明白为什么equals() 方法并不总是被调用。无论如何,在一般意义上,HashSet 确实使用equals() 进行相等性测试。
    • 谢谢 jtahlborn - 我听从了你的建议,看看你的意思。如果 hashCode() 不同,则算法不会计算 equals(),如果 hashCode() 相同,它只使用 equals()。大概这是因为 hashCode() 被认为比 equals() 计算得更快,还是与 hashCode() 必须被计算的事实有关?所以最好在文档中说: e==null ? e2==null : e.hashCode() == e2.hashCode() ? e.hashCode() == e2.hashCode() : e.equals(e2)==0
    • 抱歉 - 编辑时间用完了:e==null ? e2==null : e.hashCode() == e2.hashCode() ?真:e.equals(e2)
    【解决方案2】:

    TreeSet 在其文档中对此进行了解释:

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

    对于HashSet,文档隐含期望Set中的对象被正确实现;如果hashCode() 未正确实现,则不是HashSet 违反其规范,而是传递给它的对象。

    【讨论】:

    • "集合的行为是明确定义的,即使它的顺序与 equals 不一致。"但是,该行为与文档中未定义,这就是我想知道的。为什么文档对此不具体(准确)?最好说: e==null ? e2==null : e.compareTo(e2)==0)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-26
    • 1970-01-01
    • 1970-01-01
    • 2015-05-18
    • 1970-01-01
    相关资源
    最近更新 更多