本文介绍了Java8 Stream超过订单的集合一致性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,Set in java是一个无序集合,迭代器将按照其选择的某个顺序处理项目(我可能在这里错了),但确保它处理集合中的所有元素。

From what i understand, Set in java is an unordered collection and an iterator will process the items in some certain order of its choice(I might be wrong here) but ensures it process all the elements in the set.

在Java8中,集合中的stream()API已经引入了跳过和限制功能。所以我想知道从流处理的项目的顺序是否保持相同,无论我开始流的次数或每次都是随机的?如果在流之间修改集合,订单会改变吗?

In Java8, stream() API in Collections has been introduced with skip and limit functionality. So i want to know if the order of the items processed from stream remain same irrespective of how many times i start a stream or will it be random everytime ? Will the order change if the set gets modified in between the streams ?

可能无关紧要但我在这里提供问题:
现在出现问题,我有一套2000或者其他什么东西在创建后不会被修改,我正在进行50次批量操作,涉及每个批次的网络调用。我有一个启动参数,每次调用后会增加50。如果我在我的Set上使用一个流,其中start作为每个批次的skip参数,那么它对于每个批次都是一个新流吗?因此,流程的顺序保持不变。显然我不会多次相同的条目,更重要的是我不会错过任何条目。最简单的事情是对我来说是一个Arraylist,但我想知道我是否真的需要创建一个集合。

May be irrelevant but i am providing the problem here :Now coming to the problem, I have a Set of size 2000 or something which wont be modified post creation and i am doing a batch operation for 50 involving a network call for each batch. I have a start param which gets incremented by 50 post every batch call. If i use a stream over my Set with "start" as the skip argument for every batch, it would be a new stream for every batch right ? So is the order of the stream gaurenteed to remain same. Obviously i dont wont the same entry multiple times and more importantly i dont wont to miss out on any entry. Simplest thing is for me to an Arraylist but i want to know if it is really required for me to create a set.

推荐答案

让我们从这里的例子开始吧。首先我认为是显而易见的:

Let's start with an example here. First the obvious one I think:

List<String> wordList = Arrays.asList("just", "a", "test");

    Set<String> wordSet = new HashSet<>(wordList);

    System.out.println(wordSet);

    for (int i = 0; i < 100; i++) {
        wordSet.add("" + i);
    }

    for (int i = 0; i < 100; i++) {
        wordSet.remove("" + i);
    }

    System.out.println(wordSet);

输出将显示不同的订单 - 因为我们已经使容量更大(通过 1-100 另外)并且条目已经移动。它们仍然在那里 - 但是顺序不同(如果可以称之为顺序)。

Output will show a different "order" - because we have made the capacity bigger (via 1-100 addition) and entries have moved. They are still 3 there - but in different order (if such can be called order).

所以,是的,一旦你在流操作之间修改 Set ,订单就会改变。

So, yes, once you modify your Set between stream operations, the "order" could change.

由于您说创建后的 Set 将不会被修改 - 此时订单将被保留,在当前的实施(无论是什么)。或者更确切地说,它不是内部随机化的 - 一旦条目被放入 Set

Since you say that post creation the Set will not be modified - the order is preserved at the moment, under the current implementation (whatever that is). Or more accurately it is not internally randomized - once entries are laid into the Set.

但是这绝对不是一个人依赖的东西。事情可以在没有通知的情况下改变,因为合同被允许这样做 - 文档不对任何订单做任何保证 - Set s关于唯一性毕竟。

But this is absolutely something not to rely one - ever. Things can change without notice, since the contract is allowed to do that - the docs don't make any guarantees about any order what-so-ever - Sets are about uniqueness after all.

举个例子来说明jdk-9 Immutable Set Map 有内部随机化,订单会在不同运行中发生变化:

To give you an example the jdk-9 Immutable Set and Map do have an internal randomization and the "order" will change from run to run:

Set<String> set = Set.of("just", "a", "test");
System.out.println(set);

允许打印:

 [a, test, just] or [a, just, test]

编辑

以下是随机化模式的样子:

Here is how the randomization pattern looks like:

/**
 * A "salt" value used for randomizing iteration order. This is initialized once
 * and stays constant for the lifetime of the JVM. It need not be truly random, but
 * it needs to vary sufficiently from one run to the next so that iteration order
 * will vary between JVM runs.
 */
static final int SALT;
static {
    long nt = System.nanoTime();
    SALT = (int)((nt >>> 32) ^ nt);
}

这是做什么的:

需要很长的时间,将前32位与最后32位进行异或,并从该长度中取最后32位(通过强制转换为int)。使用XOR是因为它有50%的零和1分布,所以它不会改变结果。

take a long, XOR the first 32 bits with the last 32 bits and take the last 32 bits from that long (by casting to int). XOR is used because it has a 50% zeroes and ones distribution, so it does not alter the result.

如何使用(对于例如,设置两个元素的

// based on SALT set the elements in a particular iteration "order"
if (SALT >= 0) {
   this.e0 = e0;
   this.e1 = e1;
} else {
   this.e0 = e1;
   this.e1 = e0;

我对jdk9内部随机化部分的猜测,最初取自,相关部分:

My guess on the jdk9 internal randomization part, initially taken from here, the relevant part:

所以它是基本上打破所有依赖于 Set / Map 的订单的代码。当人们从java-7迁移到java-8并且依赖于HashMap的顺序( LinkedNode s)时,同样的事情发生了,由于,这是不同的TreeNode 的介绍。如果你留下这样的功能并且人们依赖它多年 - 很难删除它并执行一些优化 - 比如HashMap移动到 TreeNode s;因为现在你被迫保留这个命令,即使你不想这样做。 但这显然只是猜测,请将其视为

So it's basically to break all that code that would rely on order for a Set/Map. The same thing happened when people moved from java-7 to java-8 and were relying on HashMap's order (LinkedNodes), that was different due to TreeNodes introduction. If you leave a feature like that and people rely on it for years - it's hard to remove it and perform some optimizations - like HashMap moved to TreeNodes; because now you are forced to preserve that order, even if you don't want to. But that is just a guess obviously, treat it as such please

这篇关于Java8 Stream超过订单的集合一致性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-14 00:37