• Java之stream流浅析


    Stream流是Java8中提供的一个重要新特性,它允许开发人员以声明方式处理集合。其中parallelStream其实就是一个并行执行的流,它通过默认的ForkJoinPool,可能提高你的多线程任务的速度。
    Stream流特点如下

    • stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果;
    • stream不会改变数据源,通常情况下会产生一个新的集合;
    • stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行;
    • stream不可复用,对一个已经进行了终端操作的流再次调用会抛出异常;

    Stream流接口中定义了许多对于集合的操作方法,主要分为两类:中间操作和终端操作。
    在这里插入图片描述

    • 中间操作:返回一个流,通过这种方式可以将多个中间操作连接起来,形成一个调用链,从而转换为另一个流。除非调用链后存在一个终端操作,否则中间操作对流不会进行任何结果处理。
    • 终端操作:返回一个具体的结果,如list等。

    常见的中间操作方法有:limit、skip、distinct、sorted等。
    常见的终端操作方法有:forEach、count、toArray、reduce等。
    常见的收集操作方法有:collect。
    使用Stream流的方式操作完毕后,通过收集方法collect将数据收集到集合中,工具类Collectors提供了具体的收集方式,如下

    • toList:把元素收集到List集合中;
    • toSet:把元素收集到Set集合中;
    • toMap:把元素收集到Map集合中;

    Stream性能

    • 在少数据量场景(size<1000)
      stream流的foreach处理效率不如iterator迭代的效率,但实际上这些处理任务本身运行实际都低于毫秒,这点效率的差距对普通业务几乎没有影响,而stream流却可以使得代码更简单优雅;
    • 在多数据量场景(size>10000)
      stream流的foreach处理效率高于iterator迭代的效率,特别是使用了并行流,在cpu恰好将线程分配到多个核心的条件下,效率很高。
    • parallelStream并行流
      parallelStream受cpu环境影响很大,当没分配到多个cpu核心时,加上引入了forkJoinPool的开销,运行效率还不如stream流。

    下面分别对for循环、foreach循环、stream.foreach循环、parallelStream.foreach循环的性能进行测试

    public static void main(String[] args) {
            List<Integer> list = new ArrayList<Integer>();
            for (int i = 0; i < 1000; i++) {
                list.add(i);
            }
            Long startTime = System.currentTimeMillis();
            forMethod(list);
            Long endTime = System.currentTimeMillis();
            System.out.println("result:" + (endTime - startTime));//29 15 31 15 16
        }
    
        private static void forMethod(List<Integer> list) {
            for (Integer i : list) {
                System.out.println("------" + i);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    public static void main(String[] args) {
            List<Integer> list = new ArrayList<Integer>();
            for (int i = 0; i < 1000; i++) {
                list.add(i);
            }
            Long startTime = System.currentTimeMillis();
            foreachMethod(list);
            Long endTime = System.currentTimeMillis();
            System.out.println("result:" + (endTime - startTime));//85 80 84 84 85
        }
    
        private static void foreachMethod(List<Integer> list) {
            list.forEach(integer -> {
                System.out.println("------" + integer);
            });
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    public static void main(String[] args) {
            List<Integer> list = new ArrayList<Integer>();
            for (int i = 0; i < 1000; i++) {
                list.add(i);
            }
            Long startTime = System.currentTimeMillis();
            streamMethod(list);
            Long endTime = System.currentTimeMillis();
            System.out.println("result:" + (endTime - startTime));//116 115 85 84 84
        }
    
        private static void streamMethod(List<Integer> list) {
            list.stream().forEach(integer -> {
                System.out.println("------" + integer);
            });
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    public static void main(String[] args) {
            List<Integer> list = new ArrayList<Integer>();
            for (int i = 0; i < 1000; i++) {
                list.add(i);
            }
            Long startTime = System.currentTimeMillis();
            parallelStreamMethod(list);
            Long endTime = System.currentTimeMillis();
            System.out.println("result:" + (endTime - startTime)); //179 138 140 122 175
        }
    
        private static void parallelStreamMethod(List<Integer> list) {
            list.parallelStream().forEach(integer -> {
                System.out.println("------" + integer);
            });
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在数据量为1000时,效率依次是for>foreach>stream.foreach>parallelStream.foreach。
    理论上,数据量越大,stream的效率越高,parallelStream的效率会最高且是并行处理。但选用需思考其场景,避免数据安全问题。

  • 相关阅读:
    docker安装nexus3并配置统一前缀url prefix
    2 Keil自带的8051汇编boot源码解析注释
    代码,敲开新世界的大门
    [附源码]计算机毕业设计JAVA电竞选手信息管理系统论文2022
    LongAdder的源码学习与理解
    [附源码]计算机毕业设计志愿者服务平台Springboot程序
    arm-linux 原子操作
    泛微E9,独立选择框对应数据库表查询
    PHP 数码公司运营管理系统mysql数据库web结构apache计算机软件工程网页wamp
    相机等效焦距
  • 原文地址:https://blog.csdn.net/leijie0322/article/details/125415415