每次需要一个没有重复的序列时,使用 Set 而不是 Seq 是一个好习惯吗?

Is it a good practice to use Set instead of Seq every times a sequence without duplicates is needed?

几天前我发现了 Set,我知道每次我需要 sequence 而没有 duplicates 时使用它,即使我确定不会有任何。正因为如此,我在代码中经常需要使用toSet方法。

因此,我现在想知道每次我需要 sequence 而不使用 duplicates 时使用 Set 而不是 Seq 是否是一个好习惯?

还有一个额外重要的 属性 集合,它们没有明确的顺序。如果您的 collection 适合这个,那么使用 Set 是个好主意。 (所以,如果你达到 toSet,那么这可能是个好主意 tm)

如果顺序是由 Set 中的某些 属性 值定义的,那么您可以使用 SortedSet

另一方面,如果它是具有定义顺序的值序列,不基于某些 属性 值,但您想要唯一值,那么 Set 不是一个好选择合身。您可以使用 Seq.distinct 仍然有一个 Seq 但没有重复。

如果您确定不会重复,那么您应该使用 Seq,例如 Vector。原因是 Set 有额外的开销:它必须散列每个元素并可能检查与其他一些元素的相等性。根据您拥有的元素数量和它们的复杂程度,这可能是您想要避免的事情。

演示:

class A(val name: Int) {
  override def hashCode() = {
    println(f"hashing $name")
    name.hashCode
  }
  override def equals(other: Any) = other match {
    case a: A =>
      println(f"$name =?= ${a.name}")
      name == a.name
    case _ => false
  }
}


val elements = (0 to 10).map(new A(_))

println("TO VECTOR")
val seq = Vector.empty ++ elements

println("TO SET")
val set = Set.empty ++ elements

打印:

TO VECTOR    // Notice no extra work was done
TO SET       // Lots of extra stuff done:
1 =?= 0
2 =?= 0
2 =?= 1
3 =?= 0
3 =?= 1
3 =?= 2
4 =?= 0
4 =?= 1
4 =?= 2
4 =?= 3
hashing 0
hashing 1
hashing 2
hashing 3
hashing 4
hashing 5
hashing 6
hashing 7
hashing 8
hashing 9
hashing 10