【问题标题】:What do the Guava JavaDocs mean by sets being based on different "equivalence relations"?Guava JavaDocs 的集合基于不同的“等价关系”是什么意思?
【发布时间】:2018-03-27 22:03:23
【问题描述】:

Sets.SetView.union()(以及intersection()、difference() 和symmetricDifference())的番石榴JavaDocs 提到“等价关系”:

如果set1 和set2 是基于不同等价关系的集合(如HashSet、TreeSet 和IdentityHashMap 的Map.keySet() 都是),则结果未定义。

我很难理解那句话的意思。

词汇表defines "equivalence relation" 为reflexive(“a.relation(a) 始终为true”)、symmetric(a1.relation(a2) == a2.relation(a1))和transitive(a1.relation(a2) && a2.relation(a3) 暗示a1.relation(a3)) - 并指Object.equals()' docs。 (很遗憾,Guava wiki 没有详细说明...

但是不同类型的Set 在这方面有何不同(即等价关系)?他们似乎都继承了equals() from AbstractSet?它与集合持有的对象类型无关(例如Set<Cow> 与Set<Chicken>),对吗?

【问题讨论】:

    标签: java collections set guava equivalence


    【解决方案1】:

    听起来他们指的是Set 出于某种原因不使用equals 和hashCode 来比较元素。最常见的示例是带有自定义Comparator 的TreeSet。例如,我们可以有这样的东西:

    Set<String> a = new TreeSet<>();
    Set<String> b = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
    

    a和b的并集、交集等是未定义的,因为a和b在元素之间定义了不同的等价关系。

    Java SE 在谈到与equals 不一致的排序时也提到了这种情况(参见TreeSet):

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

    【讨论】:

    • 这让我有点困惑。对我来说,实现Sets.union 似乎很容易,这样它就可以按预期适用于不同的等价关系。 Set 只是一个谓词和一个迭代器,所以 union(a, b) 只是 contains(x): a.contains(x) &amp;&amp; b.contains(x) 和 iterator(): a.iterator().concat(b.iterator().filter(x -&gt; ! a.contains(x)))等价关系?
    • @MikeFHay 我认为问题在于以一种有意义的方式为联合结果创建Set。 Here's a short example. 当例如使用由IdentityHashMap 支持的集合,我们必须以另一个身份集合返回结果,否则看起来“不正确”,因为重复的元素(根据Set 合同)将被删除。如果我们确实以恒等集的形式返回结果,它会弄乱普通集的并集。如果 Java 有更好的克隆 API,这可以部分解决,但不适用于集合具有不同等价关系的情况。
    • 我不认为你的例子准确地代表了这个问题。 Guava 文档说Results are undefined if set1 and set2 are sets based on different equivalence relations,但在您的示例中,您将两个具有相同等价关系(身份)的集合合并。 Guava 的union 也是一个视图——它实际上并没有创建一个新的集合,只是使用现有的集合实现了 Set 接口,正如我在评论中所描述的那样。您在选择新实现时遇到的问题不是这种方法的问题。
    • @MikeFHay 如果您混合具有不同等价关系的集合,问题与我的示例所指出的相同。在我的示例中使用集合,联合可以是[X,X] 或[X],具体取决于使用的等价关系。在 Guava 的情况下,迭代顺序由 JavaDoc 定义的方式,您实际上会得到 union(a,b) 和 union(b,a) 的不同集合,这非常糟糕,因为联合应该是可交换的。 Here's a paste of a Guava example.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-09
    • 1970-01-01
    • 2012-12-31
    相关资源
    最近更新 更多