繁体   English   中英

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

[英]Understanding order of elements in stream generated from HashSet

我读了这篇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;
    }
}

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

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

确实存在一些误解。 HashSet或任何Set不是关于顺序的,除非基于Comparator排序的TreeSet

目前,在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);

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

[red, orange, green, blue]

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

    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]

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

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

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

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

您所看到的基本上是运气,您正在流式传输的HashSet按顺序返回值。 如果随着时间的推移添加了足够的值,最终会看到来自流的不同结果,因为HashSet的底层HashMap必须调整自身并重新排序。

你提供的(四种颜色)偶然会每次返回相同的结果,因为底层的HashMap不需要调整自身大小并重新排序值。

请记住,根据Java API文档,HashSet由HashMap支持,这个问题及其接受的答案涵盖了您通过解释HashMap的行为而看到的内容:

从HashMap检索的值的顺序

重复执行可能会产生不同的结果

might就是这个词。 即使它不保证订单,也不意味着订单每次都是随机的。 元素基于hashcode放置。 尝试一些不同的值:

    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 + " "));

输出是这样的:

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

如您所见,此示例中的顺序不同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM