Understanding the order of elements in a stream generated from a HashSet

I read the official Java 8 docs:

Streams may or may not have a specific order of meetings. One way or another, the stream has an order of meetings, depending on the source and intermediate operations. Certain stream sources (such as List or arrays) are internally ordered, while others (such as HashSet) are not.
If the flow is streamlined, repetition of identical flow pipelines at the same source will produce the same result; if it is not ordered, repeated execution may lead to different results.

Tried to understand the mentioned behavior through this code

public class StreamOrderValidator { public static void main( String[] args ) { String[] colors=new String[] {"red","green","blue","orange"}; List<String> colorsList=Arrays.asList(colors); HashSet<String> colorsSet=new HashSet<>(); colorsSet.addAll(colorsList); System.out.println(colorsSet); // [red, orange, green, blue] List<String> processedColorsSet = processStream(colorsSet.stream()); System.out.println(processedColorsSet); // [RED, ORANGE, GREEN, BLUE] } private static List<String> processStream(Stream<String> colorStream) { List<String> processedColorsList = colorStream.filter(s->s.length()<=6). map(String::toUpperCase).collect(Collectors.toList()); return processedColorsList; } } 

I have run this code many times, and the order of the elements in the resulting stream has always been the same (shown as a comment). I cannot understand how this justifies the text quoted above that "Order is not saved for an unordered collection."

I definitely misunderstand the extracted text from javadocs.

+7
java java-8 java-stream hashset
source share
3 answers

In fact, there is a little perplexity. A HashSet or any Set not about order, if a TreeSet that is ordered based on a Comparator .

At the moment, under java-8, when you put elements in a HashSet (and do not change it) - there will be an order of how the elements will be laid out; but again, provided that you do not add or remove any of them. This can change at any given time, so do not rely on it.

For example, follow these steps:

  String[] colors = new String[] { "red", "green", "blue", "orange" }; List<String> colorsList = Arrays.asList(colors); HashSet<String> colorsSet = new HashSet<>(); colorsSet.addAll(colorsList); System.out.println(colorsSet); 

How many times in java-8 at the moment you always get the same result:

 [red, orange, green, blue] 

But as soon as you do the internal shuffling:

  for (int i = 0; i < 1000; ++i) { colorsSet.add("" + i); } for (int i = 0; i < 1000; ++i) { colorsSet.remove("" + i); } System.out.println(colorsSet); // [blue, red, green, orange] 

You can see that the output changes because Set is out of order. The key point is that there is no order, the fact that you see the order is not a guarantee that it will occur every time - there may be an assembly in java-8 that will violate this order. And in fact, this is easy to observe using java-9 , for example - where is the randomization pattern for the new Set s.

If you run this several times, the result will be different:

  Set<String> set = Set.of("red", "green", "blue", "orange"); System.out.println(set); 

Thus, it is obvious that you stream from such a Set , the order will not be guaranteed, and therefore, you really will see different results from launch to launch.

+5
source share

What you see is basically luck in that the HashSet streaming returned by you returns the values ​​in sequential order. If you add sufficient values ​​over time, you will end up seeing different results from the stream due to the fact that the HashSet underlying the HashMap needs to resize and reorder.

What you set (four colors) would randomly return the same results every time, since there is no need for the underlying HashMap to resize and reorder the values.

Given that the HashSet is supported by the HashMap for java API documents, this question and the accepted answer cover what you see by virtue of explaining the behavior of the HashMap:

The order of values ​​obtained using the HashMap

+4
source share

repeated execution can lead to different results.

This is the word might . Even if this does not guarantee order, this does not mean that the order will be random every time. Elements are hosted based on hashcode . Try a few values:

  String[] colors=new String[] {"5reegdfg","fsdfsd6546","fsdfxvc4","77ggg"}; List<String> colorsList=Arrays.asList(colors); HashSet<String> intSet =new HashSet<>(); intSet.addAll(colorsList); intSet.forEach(e -> System.out.print(e + " ")); System.out.println(); intSet.add("fvcxbxb78ok"); intSet.forEach(e -> System.out.print( e + " ")); 

Output:

 fsdfxvc4 5reegdfg 77ggg fsdfsd6546 fsdfxvc4 fvcxbxb78ok 5reegdfg 77ggg fsdfsd6546 

As you can see, the order in this example is different.

+2
source share

All Articles