2

Why sameElements returned true for sets? Sets do not put elements in any order. In following two examples, the first one returns true but the second one returns false.

scala> val xs1 = Set(3, 2, 1, 4, 5, 6, 7)
xs1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 4)

scala> val ys1 = Set(7, 2, 1, 4, 5, 6, 3)
ys1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 4)

scala> xs1 sameElements ys1
res7: Boolean = true 


scala> val xt1 = Set(1, 2, 3)
xt1: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

scala> val yt1 = Set(3, 2, 1)
yt1: scala.collection.immutable.Set[Int] = Set(3, 2, 1)

scala> xt1 sameElements yt1
res8: Boolean = false
Manu Chadha
  • 15,555
  • 19
  • 91
  • 184
  • I would suspect that order of elements in the Set is not guaranteed to be exact as you defined in the code, so internal logic and change of order could be applied. – Pavel Oct 19 '17 at 11:05
  • Possible duplicate of [Scala Sets contain the same elements, but sameElements() returns false](https://stackoverflow.com/questions/29008500/scala-sets-contain-the-same-elements-but-sameelements-returns-false) – C4stor Aug 09 '18 at 15:04

1 Answers1

2

For scala.collection.immutable.Set.sameElements(Set) to return true, both sets need to have the same elements, in the same order.

The default Set implementations are not ordered, so the element ordering depends upon the storage algorithm and the order in which elements were added. In your first example, the ordering turned out to be the same purely by coincidence.

If you use a scala.collection.immutable.SortedSet instead, you should get what you expect.

EDIT: If you want to just check whether two sets contain the same elements, regardless of order, just use equals. To illustrate this, try the following:

scala> val xt1 = Set(1, 2, 3)
xt1: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

scala> val yt1 = Set(3, 2, 1)
yt1: scala.collection.immutable.Set[Int] = Set(3, 2, 1)

scala> xt1 sameElements yt1
res0: Boolean = false

scala> xt1 == yt1
res1: Boolean = true

So sameElements is useful if you need to determine whether the ordering is the same as well as the elements themselves; otherwise, just use good ole ==.

Mike Allen
  • 8,139
  • 2
  • 24
  • 46
  • This doesn't feel right to me. Sets aren't ordered, so the order shouldn't depend on anything - it should not exist at all semantically. That is, two sets that contain the same elements should be indistinguishable from each other, no matter in which sequence the elements were added. Note that this is the case for most Set implementations, just not the special-cased ones (`Set.Set2` through `Set.Set4`). I'd consider this a bug in those classes. – sepp2k Oct 19 '17 at 12:04
  • 1
    @sepp2k it doesn't matter what you feel. :-) It matters [what the documentation for the function states](http://www.scala-lang.org/api/current/scala/collection/mutable/Set.html): "Checks if the other iterable collection contains the same elements in the same order as this set." – Mike Allen Oct 19 '17 at 12:08
  • 1
    If you want to check if they contain the same elements, you can just use `==`. (For example, in the OP's original post, if you type `xt1 == yt1`, what do you get?) – Mike Allen Oct 19 '17 at 12:12
  • I do not want to check that two sets are the same. I was surprised to see this behavior. In my opinion and based on your answers, using `sameElements` for `Set` isn't reliable. – Manu Chadha Oct 19 '17 at 12:48
  • @ManuChadha I agree that `sameElements` might be a bit of a misnomer, because there are two different interpretations of what that name might mean. However, if you want to check if two sets contain the same elements, use `equals` or `==` (to check if the two sets are equivalent). If the order matters - and it often does - `equals` is inadequate, hence the need for `sameElements`. Same elements **is** reliable, but only when you understand what it does. If you want sets that are ordered, use a `SortedSet` or `TreeSet` implementation. – Mike Allen Oct 19 '17 at 12:52
  • @ManuChadha Using `sameElements` on a `SortedSet` is practically identical to using `equals` or `==` on a regular, unordered `Set`. So is there a use case for using `sameElements` with a `Set`? Who knows? Possibly not. It does provide an extra layer of _equality_. Either way, it's inherited by all _iterable_ collections, and it does make sense for many non-`Set` collections. Did I answer your original question? – Mike Allen Oct 19 '17 at 13:08