在使用Scala exercises on Iterables时,我遇到了以下奇怪的行为:
val xs = Set(5,4,3,2,1)
val ys = Set(1,2,3,4,5)
xs sameElements ys // true
val xs = Set(3,2,1)
val ys = Set(1,2,3)
xs sameElements ys // false - WAT?!
当然这些集合具有相同的元素,应该忽略排序;为什么这只能用于较大的集合?
答案 0 :(得分:91)
Scala集合库为少于5个值的集合提供专门的实现(请参阅source)。这些实现的迭代器按照添加它们的顺序返回元素,而不是用于较大集合的基于哈希的一致排序。
此外,sameElements
(scaladoc)已在Iterable
上定义(已在IterableLike
中实施 - 请参阅source);只有当迭代器以相同的顺序返回相同的元素时,它才返回true。
虽然Set(1,2,3)
和Set(3,2,1)
应该等效,但它们的迭代器不同,因此sameElements
返回false。
这种行为令人惊讶,可以说是一个错误,因为它违反了Set的数学期望(但仅限于Set的某些大小!)。
作为I.K.在评论中指出,==
如果您只是将集合彼此进行比较,即Set(1,2,3) == Set(3,2,1)
,则可以正常工作。但是,sameElements更通用,因为它可以比较任何两个iterables的元素。例如,List(1, 2, 3) == Array(1, 2, 3)
为false,但List(1, 2, 3) sameElements Array(1, 2, 3)
为真。
更一般地说,平等可能令人困惑 - 请注意:
List(1,2,3) == Vector(1,2,3)
List(1,2,3) != Set(1,2,3)
List(1,2,3) != Array(1,2,3)
Array(1,2,3) != Array(1,2,3)
submitted a fix Scala exercises解释了sameElements
问题。