简体   繁体   English

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

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

I read this Java 8 official docs: 我读了这篇Java 8官方文档:

Streams may or may not have a defined encounter order. 流可能有也可能没有已定义的遭遇顺序。 Whether or not a stream has an encounter order depends on the source and the intermediate operations. 流是否具有遭遇顺序取决于源和中间操作。 Certain stream sources (such as List or arrays) are intrinsically ordered, whereas others (such as HashSet) are not. 某些流源(例如List或数组)本质上是有序的,而其他流(例如HashSet)则不是。
If a stream is ordered, repeated execution of identical stream pipelines on an identical source will produce an identical result; 如果订购了流,则在相同的源上重复执行相同的流管道将产生相同的结果; if it is not ordered, repeated execution might produce different results. 如果没有订购,重复执行可能会产生不同的结果。

Tried to understand the mentioned behaviour 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 ran this code many a times and the order of elements in resulting stream was always the same (shown as comment). 我多次运行此代码,结果流中元素的顺序始终相同(显示为注释)。 I am not able to figure it out how this justifies the above quoted text about "Order not being preserved for an unordered collection". 我无法弄清楚这是如何证明以上引用的文字有关“命令不被保留为无序集合”。

I am definitely misunderstanding the extracted text from javadocs. 我肯定误解了javadocs提取的文本。

There is a little bit of mis-understating here indeed. 确实存在一些误解。 A HashSet or any Set is not about order, unless TreeSet that is ordered based on a Comparator . HashSet或任何Set不是关于顺序的,除非基于Comparator排序的TreeSet

At the moment, under java-8 once you put elements into a HashSet (and don't change it) - there will be an order of how the elements are laid out; 目前,在java-8下,一旦你将元素放入HashSet (并且不改变它),就会有一个如何布置元素的顺序; but again, under the condition that you do not add or remove any of them. 但同样,在你不添加或删除任何一个的情况下。 This can change at any point in time, so don't rely on it. 这可以随时改变,所以不要依赖它。

For example running this: 比如运行这个:

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

No matter how many times under java-8 at the moment you will always get the same output: 你会不管多少次下的java-8 的时刻 总是得到相同的输出:

[red, orange, green, blue]

But once you do some internal re-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 s don't have an order. 您可以看到输出更改,因为Set s没有订单。 The key point to take is that there is no order, the fact that you do see an order is not a guarantee to happen every time - there might be a build in java-8 that will break this order. 要点是没有顺序,事实上你确实看到订单并不是每次都发生的保证 - 在java-8中可能会有一个破坏这个顺序的构建。 And in fact that is easily observable with java-9 for example - where there is a randomization pattern for new Set s. 事实上,例如java-9很容易观察到 - 其中有新的Set的随机化模式。

If you run this multiple times, the result will differ: 如果多次运行,结果会有所不同:

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

So obviously of you stream from such a Set the order will not be guaranteed and thus you will indeed see different results from run to run. 很明显,你从这样的Set stream ,订单将无法保证,因此你确实会看到不同的运行结果。

What you're seeing is basically luck that the HashSet you're streaming returns values in sequential order. 您所看到的基本上是运气,您正在流式传输的HashSet按顺序返回值。 If you added enough values over time, you would eventually see different results from the stream due to the HashSet's underlying HashMap having to resize itself and re-order. 如果随着时间的推移添加了足够的值,最终会看到来自流的不同结果,因为HashSet的底层HashMap必须调整自身并重新排序。

What you've supplied (the four colors) would, by chance, return the same results each time since there's no need for the underlying HashMap to resize itself and re-order values around. 你提供的(四种颜色)偶然会每次返回相同的结果,因为底层的HashMap不需要调整自身大小并重新排序值。

Bearing in mind that a HashSet is backed by a HashMap per the java API docs, this question and its accepted answer covers what you're seeing by virtue of explaining a HashMap's behavior: 请记住,根据Java API文档,HashSet由HashMap支持,这个问题及其接受的答案涵盖了您通过解释HashMap的行为而看到的内容:

Order of values retrieved from a HashMap 从HashMap检索的值的顺序

repeated execution might produce different results. 重复执行可能会产生不同的结果

There's this might word. might就是这个词。 Even if it does not guarantee the order, it doesn't mean that order will be random every time. 即使它不保证订单,也不意味着订单每次都是随机的。 Elements are placed based on the hashcode . 元素基于hashcode放置。 Try some different 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 + " "));

The output is this : 输出是这样的:

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

As you can see, the order is different in this example. 如您所见,此示例中的顺序不同。

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

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