Java 8 findFirst并遇到订单 [英] Java 8 findFirst and encounter order

查看:115
本文介绍了Java 8 findFirst并遇到订单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

的JavaDocs> findFirst 表示如果流具有遭遇顺序,则将始终返回第一个元素,但如果流没有遇到顺序,则可能会返回任何元素。

The JavaDocs for findFirst say that if the stream has an encounter order, then the first element will always be returned, but if the stream does not have an encounter order, any element may be returned.

我正在尝试演示如何在没有遭遇顺序的流上工作,但我无法让它返回除实际第一个元素之外的任何内容。

I'm trying to demonstrate how this works on a stream without an encounter order, but I can't get it to return anything other than the actual first element.

我尝试将元素添加到 Set ,但没有定义的遭遇订单:

I tried adding the elements to a Set, which does not have a defined encounter order:

    Set<String> words = new HashSet<>();
    words.addAll(Arrays.asList("this", "is", "a", "stream", "of", "strings"));
    Optional<String> firstString = words.stream()
            .findFirst();
    System.out.println(firstString);

每次运行时,我都会得到 a 作为第一个字符串。然后我尝试在列表上执行 Collections.shuffle ,然后将其添加到 Set ,但这并未改变任何内容。

Every time I run, I get a as the first string. Then I tried doing a Collections.shuffle on the List before adding it to the Set, but that didn't change anything.

    List<String> wordList = Arrays.asList("this", "is", "a", "stream", "of", "strings");
    words = new HashSet<>();
    words.addAll(wordList);
    firstString = words.stream()
            .findFirst();
    System.out.println(firstString);

我仍然会回复 a 这个词时间。

I still get back the word a every time.

然后我尝试使用 BaseStream 无序方法c>,声称返回没有遇到订单的流,但没有区别:

Then I tried using the unordered method from BaseStream, which claims to return a stream without encounter order, but no difference:

    firstString = Stream.of("this", "is", "a", "stream", "of", "strings")
            .unordered()
            .findFirst();
    System.out.println(firstString);

现在我每次都得到这个这个词。我错过了什么吗?有没有办法证明无序流上的 findFirst 返回不同的值?

Now I get the word this every time. Am I missing something? Is there some way to demonstrate that findFirst on an unordered stream returns different values?

推荐答案

嗯,任何包括第一的可能性。当然,Stream实现不会浪费随机化数据的工作,因此对于很多情况,特别是顺序执行,它仍然是第一个元素,如果我们可以这样调用它(因为没有命令,有没有尊重的第一个元素。)

Well, "any" includes the possibility of "first". Of course, the Stream implementation does not waste efforts in randomizing the data, so for a lot of cases, especially with sequential execution, it will still be the first element, if we can call it that way (as without an order, there is no distinguished first element).

findFirst 展示不同结果的最佳机会是使用并行Streams。但即便如此,并非所有操作组合都适合展示无序性。

Your best chances of exhibiting different results for findFirst are with parallel Streams. But even there, not every combination of operations is suitable of exhibiting the unorderedness.

有一点是,在当前实现中, findFirst() 操作在Stream无序时不会改变它的行为,即它不会主动尝试像 findAny ()。由于流的,它可能仍会出现不可预测的行为,但如果您的来源是 Stream.of(this,is,a,stream ,,,字符串),即一个已知大小的不可变序列,它已经具有最佳的并行性能,因此根本无法获得链式<$的好处c $ c> unordered(),因此,当前的实现不会改变它的行为。

One point is, that in the current implementation, the findFirst() operation does not change it’s behavior when the Stream is unordered, i.e. it does not actively try to be like findAny(). It may still exhibit unpredictable behavior due to the source of the Stream, but if your source is Stream.of("this", "is", "a", "stream", "of", "strings"), i.e. an immutable sequence of a known size, it has already the best parallel performance possible, so there’s simply no way of drawing a benefit of the chained unordered(), hence, the current implementation doesn’t change its behavior.

这可能会让人感到惊讶,但这甚至适用在某种程度上到 HashSet 。虽然它有一个未指定的顺序,但在某个时间点它的支持数组中会有一个实际的订单,只要你不修改 Set ,就会有没有理由对这些条目进行随机播放,因此对于特定的 HashSet 实例,您可能会重复获取相同的第一个元素,尽管它没有指定哪个元素甚至在单个元素中运行时,另一个表示相同内容但具有不同历史记录的 HashSet 实例可能具有不同的顺序。

It might surprise, but this even applies to a HashSet to some degree. While it has an unspecified order, there will be an actual order within its backing array at some point of time and as long as you don’t modify the Set, there will be no reason to shuffle these entries around, so for a particular HashSet instance, you may repeatedly get the same "first" element, though it’s not specified which one and even within a single runtime, another HashSet instance representing the same contents, but having a different history, may have a different order.

已知从无序特征中获益的一个操作示例是 distinct 。虽然必须对重复项进行排序,但如果它产生显着差异,它必须保持第一个遇到相同的元素。这会显着降低性能,因此,如果流是无序的,实现将立即尝试获得好处。例如,

One example of an operation that is known to draw a benefit from the unordered characteristics is distinct. While it has to sort out duplicates, it has to keep the first encountered of equal elements, if it makes a notable difference. This can degrade the performance significantly, hence, the implementation will immediately try to get a benefit if the stream is unordered. E.g.

List<String> equal=IntStream.range(0, 100)
    .mapToObj(i->new String("test")) // don't do this in normal code
    .collect(Collectors.toList());
Map<String, Integer> map = IntStream.range(0, equal.size())
    .collect(IdentityHashMap::new, (m,i)->m.put(equal.get(i),i), Map::putAll);

equal.parallelStream().distinct().map(map::get)
     .findFirst().ifPresent(System.out::println);

这会产生一堆等于但可区分 String 实例(您通常不应该这样做),在 IdentityHashMap 中将它们的位置编号注册,所以我们可以找出,保留了 distinct 的实例。由于上面的代码使用由 List 创建的有序流,因此无论执行频率如何,它都会一直打印 0 它。

This creates a bunch of equal but distinguishable String instances (which you normally shouldn’t do), registers them with their positional number in an IdentityHashMap, so we can find out, which instance distinct has retained. Since the code above uses an ordered stream created by a List, it consistently prints 0, regardless of how often you execute it.

相比之下,

equal.parallelStream().unordered().distinct().map(map::get)
     .findFirst().ifPresent(System.out::println);

将打印任意数量的范围,因为我们已经发布了订购的合同并允许选择任何相同的字符串。

will print arbitrary numbers of the range, as we have released the ordered contract and allow to pick any of the equal strings.

如前所述,这是所有实现特定的。你永远不应该假设一个操作是否可以实际获得一个好处,从而改变它对无序流的行为。上面的解释仅仅是为了说明为什么有时特定实现的行为可能不会因无序流而改变。但是,它仍然可能在下一个版本或不同的JRE实现中。

As already noted before, this is all implementation specific. You should never make an assumption about whether an operation can actually draw a benefit and thus, will change its behavior for unordered streams. The explanation above was only meant to illustrate why sometimes the behavior of a particular implementation might not change for unordered stream. Though, it still might in the next version or a different JRE implementation.

这篇关于Java 8 findFirst并遇到订单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆