Search code examples
dartsetconstantsiterable

Dart - Are sets really unordered?


From the documentation:

A set in Dart is an unordered collection of unique items.

But if I run this sample code:

final a = {0, 1, 2};
final b = {2, 1, 0};
for (final i in a) {
  print('a - $i');
}
for (final i in b) {
  print('b - $i');
}
print(a == b);

I get the output

a - 0
a - 1
a - 2
b - 2
b - 1
b - 0
false

The 2 iterables a and b don't behave the same when looped over and == is false (But I guess == makes sense since the a and b are not the same instance).


However, what I don't understand is if a and b are constants:

const a = {0, 1, 2};
const b = {2, 1, 0};
for (final i in a) {
  print('a - $i');
}
for (final i in b) {
  print('b - $i');
}
print(a == b);

This yields the same output.

And if I order b as a:

const a = {0, 1, 2};
const b = {0, 1, 2};
for (final i in a) {
  print('a - $i');
}
for (final i in b) {
  print('b - $i');
}
print(a == b);

It logs:

a - 0
a - 1
a - 2
b - 0
b - 1
b - 2
true

I'm a bit surprised that const a = {0, 1, 2} and const b = {2, 1, 0} are not equal. Aren't const variable being reused, and aren't a and b supposed to be equal since sets are unordered?

What am I missing?


Solution

  • Dart sets are ordered in the sense that if you use their iterator, you get elements in some order. That order may or may not be predictable. The order is unspecified for sets in general, but some Set implementations may choose to specify a specific ordering.

    The one thing that is required is that the ordering of a set doesn't change unless the set changes. So, if you iterate the same set twice, without changing it in-between, you get the same ordering — whatever it is.

    • LinkedHashSet promises insertion ordering.
    • SplayTreeSet promises comparator ordering.
    • Constant set literals promise source ordering (first occurrence if the same value occurs more than once). They're like immutable LinkedHashSets.