【问题标题】:Why is it necessary for SortedSet's equals method to break the Set contract?为什么 SortedSet 的 equals 方法必须打破 Set 契约?
【发布时间】:2020-03-18 12:20:15
【问题描述】:

SortedSet<T>Set<T> 的实现,它维护T 类型元素的排序。

我很难理解为什么有必要按照以下文档实施SortedSetequals 方法,从而破坏Set 的一般合同:

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

当前实现

通过浏览源代码,SortedSet 的相等性似乎目前以下列方式工作。给定两个SortedSet 实例aba.equals(b) 将:

final Entry<K,V> getEntry(Object key) {
    // Offload comparator-based version for sake of performance
    if (comparator != null)
        return getEntryUsingComparator(key);
    if (key == null)
        throw new NullPointerException();
    @SuppressWarnings("unchecked")
        Comparable<? super K> k = (Comparable<? super K>) key;
    Entry<K,V> p = root;
    while (p != null) {
        int cmp = k.compareTo(p.key);
        if (cmp < 0)
            p = p.left;
        else if (cmp > 0)
            p = p.right;
        else
            return p;
    }
    return null;
}

直观的SortedSet平等

要确定两个 SortedSet 实例 ab 是否相等,我个人会:

  1. 在当前实现中执行相同的初始检查,例如大小比较
  2. 在集合a 的第一个元素上启动光标
  3. 在集合b 的第一个元素上启动光标
  4. 将元素与自己的equals方法进行比较
  5. 将两个光标移动到下一个元素并转到第 4 步,直到元素用完为止。

由于排序顺序是由ComparatorcompareTo 方法保证的,所以我看不出这不起作用的原因。

问题

  • 我上面的方法有问题吗?
  • 如果不是,为什么SortedSet 不相等?

【问题讨论】:

    标签: java set


    【解决方案1】:

    你只考虑sortedSetA.equals(sortedSetB)

    sortedSetA.equals(hashSetA) 如果元素相同,即使遍历顺序不同,也应该返回 true。

    Set::equals

    如果指定的对象也是一个集合,则返回true,这两个集合有 大小相同,并且指定集合的​​每个成员都包含在 这一套

    这就是实现遵循一般情况的原因。

    远非遵守约定,您的实现还违反了Set 的约定,因为具有以不同方式排序的相同元素的两个集合将被视为不相等。

    【讨论】:

    • 我从未声称我自己的实现遵守Set 合同 - 但感谢您的回答,这很有意义。如果我想要按照我建议的方式比较两个 SortedSet 实例的功能,这是否意味着我必须自己编写代码?
    • @PaulBenn 你问“为什么一定要违约?”并提供了一个替代实现。我认为这意味着您的实施不会违反合同。是的,你必须自己写。我检查了 Guava 和 Apache Commons——这种 util 方法最有可能出现的地方——你所描述的都没有。
    猜你喜欢
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多