【问题标题】:Scala - Collection comparison - Why is Set(1) == ListSet(1)?Scala - 集合比较 - 为什么 Set(1) == ListSet(1)?
【发布时间】:2019-02-05 10:24:52
【问题描述】:

为什么这个比较的输出是true

import scala.collection.immutable.ListSet

Set(1) == ListSet(1) // Expect false

//Output
res0: Boolean = true 

从更一般的意义上说,比较实际上是如何进行的?

【问题讨论】:

  • 实现归结为set1.forall(set2.contains)(在检查大小等之后)毫无价值,这意味着如果您要比较大集合并关心性能,ListSet 应该先来吧。

标签: scala collections comparison


【解决方案1】:

由于Set <: GenSet <: GenSetLike的继承链有点长,到哪里去找equals的代码可能不是很明显,所以我想也许我在这里引用它:

GenSetLike.scala:

  /** Compares this set with another object for equality.
   *
   *  '''Note:''' This operation contains an unchecked cast: if `that`
   *        is a set, it will assume with an unchecked cast
   *        that it has the same element type as this set.
   *        Any subsequent ClassCastException is treated as a `false` result.
   *  @param that the other object
   *  @return     `true` if `that` is a set which contains the same elements
   *              as this set.
   */
  override def equals(that: Any): Boolean = that match {
    case that: GenSet[_] =>
      (this eq that) ||
      (that canEqual this) &&
      (this.size == that.size) &&
      (try this subsetOf that.asInstanceOf[GenSet[A]]
       catch { case ex: ClassCastException => false })
    case _ =>
      false
  }

本质上,它检查另一个对象是否也是GenSet,如果是,它会尝试执行一些快速失败检查(比如比较size和调用canEqual),以及大小是否相等,它检查这个集合是否是另一个集合的子集,大概是通过检查每个元素。

因此,在运行时用于表示集合的确切类无关紧要,重要的是比较对象也是 GenSet 并且具有相同的元素。

【讨论】:

    【解决方案2】:

    来自Scala collections equality

    集合库对相等和散列有统一的方法。这个想法首先是将集合划分为集合、映射和序列。

    ...

    另一方面,在同一类别中,集合当且仅当它们具有相同的元素时才相等

    在您的情况下,两个集合都被视为集合,并且它们包含相同的元素,因此它们是相等的。

    【讨论】:

    • 这是正确的,但对于序列只有一点注意事项:List(1, 2, 3) == Vector(1, 2, 3)List(1, 2, 3) != Array(1, 2, 3)Array(1, 2, 3) != Array(1, 2, 3) - 另见stackoverflow.com/questions/29008500/…
    • Array 不是collections 包的一部分,有更多关于here 的信息Array 的特性。如果转换为Seq[Int](将其包装为WrappedArray),那么它将等于等效的List
    【解决方案3】:

    Scala 2.12.8 documentation:

    此类使用基于列表的数据实现不可变集 结构。

    所以 ListSet 也是一个集合,但具有具体的(基于列表的)实现。

    【讨论】:

      猜你喜欢
      • 2019-04-06
      • 2014-12-21
      • 1970-01-01
      • 1970-01-01
      • 2020-02-23
      • 2019-11-11
      • 2015-02-20
      • 2017-04-28
      • 2019-08-02
      相关资源
      最近更新 更多