了解从HashSet生成的流中元素的顺序

use*_*926 7 java hashset java-8 java-stream

我读了这篇Java 8官方文档:

流可能有也可能没有已定义的遭遇顺序.流是否具有遭遇顺序取决于源和中间操作.某些流源(例如List或数组)本质上是有序的,而其他流(例如HashSet)则不是.
如果订购了流,则在相同的源上重复执行相同的流管道将产生相同的结果; 如果没有订购,重复执行可能会产生不同的结果.

试图通过此代码了解上述行为

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我多次运行此代码,结果流中元素的顺序始终相同(显示为注释).我无法弄清楚这是如何证明以上引用的文字"订单不被保留为无序集合".

我肯定误解了javadocs提取的文本.

Eug*_*ene 5

确实存在一些误解.A HashSet或任何Set不是关于订单,除非TreeSet是基于a订购的Comparator.

目前,在java-8下,一旦你将元素放入一个HashSet(并且不要改变它) - 将会有一个如何布置元素的顺序; 但同样,在你不添加或删除任何一个的情况下.这可以随时改变,所以不要依赖它.

比如运行这个:

 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);
Run Code Online (Sandbox Code Playgroud)

不管有多少次下的java-8 的那一刻,你会总是得到相同的输出:

[red, orange, green, blue]
Run Code Online (Sandbox Code Playgroud)

但是一旦你做了一些内部重新洗牌:

    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]
Run Code Online (Sandbox Code Playgroud)

您可以看到输出更改,因为Sets没有订单.要点是没有顺序,事实上你确实看到订单并不是每次都发生的保证 - 在java-8中可能会有一个破坏这个顺序的构建.事实上,这很容易被观察到java-9- 例如 - 新的Sets 存在随机化模式.

如果多次运行,结果会有所不同:

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

很明显,你stream从这样Set的订单中得不到保证,因此你确实会看到不同的运行结果.