热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

以确定的方式对有序流过程元素进行有状态映射操作?

如何解决《以确定的方式对有序流过程元素进行有状态映射操作?》经验,为你挑选了1个好方法。

我正在阅读关于java流API和我从这里遇到以下声明

无论流是以串行还是并行方式执行,forOachOrdered操作都按流指定的顺序处理元素.但是,当并行执行流时,映射操作会处理由Java运行时和编译器指定的流的元素.因此,lambda表达式的顺序为e - > {parallelStorage.add(e); 返回e; 向List添加元素parallelStorage每次运行代码时都会有所不同.对于确定性和可预测的结果,请确保流操作中的lambda表达式参数不具有状态.

我测试了我的以下代码,它实际上如上所述.

    public class mapordering {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        List serialStorage = new ArrayList<>();

        System.out.println("Serial stream:");
        int j=0;
        List listOfIntegers = new ArrayList() ;
        for(int i=0;i<10;i++)listOfIntegers.add(String.valueOf(i));


           listOfIntegers.stream().parallel() .map(e -> { serialStorage.add(e.concat(String.valueOf(j))); return e; }).forEachOrdered(k->System.out.println(k));;
           /* 
            // Don't do this! It uses a stateful lambda expression.
            .map(e -> { serialStorage.add(e); return e; })*/

    for(String s:serialStorage)System.out.println(s);

    }

}

产量

串行流:0 1 2 3 4 5 6 7 8 9 null null 80 90 50 40 30 00

问题:

    每次运行时输出都会发生变化.如何编写代码以有序的方式处理statefull映射操作?

    map是中间操作,它只在终端操作开始之前才开始处理元素.因为终端操作是有序的,为什么map操作是无序的,并且每次使用statefull操作时都倾向于改变结果?

Eugene.. 7

你很幸运地看到它serialStorage具有你认为它将具有的所有元素,毕竟你是从多个线程添加多个元素到非线程安全的集合ArrayList.您可以很容易地看到nulls或a List没有所有元素.但即使你添加一个List线程安全的东西 - 绝对没有你可以依赖的顺序.

这在副作用的文档中明确提到,中间操作应该是无副作用的.

基本上有两种排序:处理订单(中间操作)和遭遇订单.保留最后一个(如果它有一个开头,流中间操作不会破坏它 - 例如unordered,sorted).

未指定处理顺序,这意味着所有中间操作都将以他们想要的顺序处理元素.遇到订单(您从终端操作中看到的订单)将保留初始订单.

但即使终端操作也不必保留初始订单,例如forEachvs forEachOrdered或收集到的时候Set; 当然阅读文档,它通常清楚地说明这方面.



1> Eugene..:

你很幸运地看到它serialStorage具有你认为它将具有的所有元素,毕竟你是从多个线程添加多个元素到非线程安全的集合ArrayList.您可以很容易地看到nulls或a List没有所有元素.但即使你添加一个List线程安全的东西 - 绝对没有你可以依赖的顺序.

这在副作用的文档中明确提到,中间操作应该是无副作用的.

基本上有两种排序:处理订单(中间操作)和遭遇订单.保留最后一个(如果它有一个开头,流中间操作不会破坏它 - 例如unordered,sorted).

未指定处理顺序,这意味着所有中间操作都将以他们想要的顺序处理元素.遇到订单(您从终端操作中看到的订单)将保留初始订单.

但即使终端操作也不必保留初始订单,例如forEachvs forEachOrdered或收集到的时候Set; 当然阅读文档,它通常清楚地说明这方面.


@amarnathharish没有.首先将`unordered`中间操作添加到流管道中不会故意改变流内的源元素.它只是在当前的实现*中设置了一个标志*; 但事情可能会改变.因此,添加`unordered`只是流中可以利用或不利用的标志,如果顺序流不是.这没关系,因为你说,你不关心秩序,总是返回*相同*结果很好,因为,你明确地说你不关心那个顺序.
@amarnathharish甚至在单线程场景中,你可以说当事情可能以某种方式改变并且那些中间操作可能以某种未定义的顺序运行时,java-15会遇到麻烦; 并且文档明确地说这是不好的(读"禁止").这里还有一个方面:`Stream.of(1,2,3).map(x - > {Syso("mapping"); return x + 1;}).count()`,在java-中运行8和java-9 ...
@amarnathharish,这不是重点...在java-9`map`中*将*不会被执行.
@amarnathharish没有,但由于中间操作应该是无副作用的,所以你不应该关心这一点.如果你这样做,那么流可能不是正确的工具
应该强调的是,终端操作的处理仍然不必按照定义的顺序(`forEachOrdered`除外),例如当你执行`collect(mapping(functionWithSideEffect,toList()))`时,它仍然是不确定的.只有最终结果,即返回的"List",才会与遭遇顺序一致.
推荐阅读
author-avatar
程武钢2011
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有