3

can you please let me know why below code returns the set sorted order given an unsorted array?

    Stream<Integer> s = Stream.of(2, 3, 1, 4, 5);

    Set<Integer> mySet = s.collect(Collectors.toSet());

    System.out.println(mySet);

O/p

1, 2, 3, 4, 5

This doesn't happen if I use List instead of Set. Also the sorting is not always correct when there are negative numbers in the input. Is there any inbuilt functionality to sort the Set?

Eager
  • 225
  • 1
  • 8
  • 1
    *Also the sorting is not always correct* See the [documentation](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toSet--]) *This is an unordered Collector.* – Jens Mar 08 '20 at 13:54

2 Answers2

6

This is just an accident and has nothing to do with Collector or Stream. On OpenJDK 11.0.2, I'm getting this (as Collector.toSet() is currently backed by HashSet):

Set<Integer> set = new HashSet<>();
set.add(2);
set.add(3);
set.add(1);
set.add(4);
set.add(5);
System.out.println(set); // [1, 2, 3, 4, 5]

But try this:

set.add(100);
System.out.println(set); // [1, 2, 3, 4, 100, 5]

It is really just an accident. A very curious one, indeed, which has to do with the Integer.hashCode() implementation (it's just the Integer.intValue() itself), and how this results in accidentally ordering HashSet elements for certain sets.

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
  • 2
    `Set::of` is immune to this, at least if run enough times – Eugene Mar 08 '20 at 16:33
  • 1
    You can also make the result more interesting by changing the construction to `new HashSet<>(4, 2f)`. Or you change the construction to `new HashSet<>(1, 5f)`, to start seeing the insertion order, apparently, but then, the `set.add(100)` destroys it… – Holger Mar 10 '20 at 09:35
1

It is just a coincidence. The Set interface does not provide any ordering guarantees, but LinkedHashSet.