Scala Sets contain the same elements, but sameElements() returns false

ScalaScala Collections

Scala Problem Overview


Whilst working through the Scala exercises on Iterables, I encountered the following strange behaviour:

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?!

Surely these Sets have the same elements, and should ignore ordering; and why does this work as expected only for the larger set?

Scala Solutions


Solution 1 - Scala

The Scala collections library provides specialised implementations for Sets of fewer than 5 values (see the source). The iterators for these implementations return elements in the order in which they were added, rather than the consistent, hash-based ordering used for larger Sets.

Furthermore, sameElements (scaladoc) is defined on Iterables (it is implemented in IterableLike - see the source); it returns true only if the iterators return the same elements in the same order.

So although Set(1,2,3) and Set(3,2,1) ought to be equivalent, their iterators are different, therefore sameElements returns false.

This behaviour is surprising, and arguably a bug since it violates the mathematical expectations for a Set (but only for certain sizes of Set!).

As I.K. points out in the comments, == works fine if you are just comparing Sets with one another, i.e. Set(1,2,3) == Set(3,2,1). However, sameElements is more general in that it can compare the elements of any two iterables. For example, List(1, 2, 3) == Array(1, 2, 3) is false, but List(1, 2, 3) sameElements Array(1, 2, 3) is true.

More generally, equality can be confusing - note that:

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)

I have submitted a fix for the Scala exercises that explains the sameElements problem.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDNAView Question on Stackoverflow
Solution 1 - ScalaDNAView Answer on Stackoverflow