首页 > 其他分享 >你OUT了吗,for双层循环可以使用stream方式替代

你OUT了吗,for双层循环可以使用stream方式替代

时间:2022-10-05 20:13:08浏览次数:53  
标签:班级 双层 Stream 迭代 学生 操作 stream OUT

本文已参与「新人创作礼」活动,一起开启掘金创作之路

大家好,我是桐言无忌,当前是不务正业的攻城狮,信奉“实践出真知,生活更简单”,向往自由。签名.PNG

糟粕代码

java8已经出了Stream流处理方式,但是实际业务开发时,大部分同学还是下意识的去写for双层循环。

陈旧代码

一眼看穿繁华。。。这段代码写法就是典型的for双层循环,我们再细看业务逻辑是判断List<T>所有对象元素中有无重复的,若有重复对象主键,则抛出业务异常。

其实业务场景不复杂,那完全可以使用Stream流处理方式,那么大家还是使用for双层循环的原因是什么呢?是习惯,还是处于性能考虑呢?

做个试验,验证看看。。。

试验场

首先模拟个场景:班级里面的学生,学生与班级的匹配,检查学生是否真正是有班级的。

  1. 先模拟学生类和班级类

    学生班级

  2. 再搞10W+的学生数量和班级数量,不是怀疑是性能吗?数量小了可不行

    学生数量

  3. 搞一个for双层循环方式

    // for双层循环的方式
    private static void doubleForMethod(List<Student> studentList, List<NoClass> noClassList) {
        // 现在用学生与班级进行匹配,如果是班级号一致,认为这个学生是本班级的
        for (int i = 0; i < studentList.size(); i++) {
            Student student = studentList.get(i);
            for (int j = 0; j < noClassList.size(); j++) {
                NoClass noClass = noClassList.get(j);
                if (student.getClassesId().equals(noClass.getClassId())) {
                    // System.out.println("该学生:" + student.getStuId() + "是有班级的");
                }
            }
        }
    }
    复制代码
  4. 再搞一个Stream流方式

    private static void streamMethod(List<Student> studentList, List<NoClass> noClassList) {
        // 把班级列表转成map,那么班级id就是唯一的id
        Map<String, NoClass> noClassMap = noClassList.stream().collect(Collectors.toMap(t -> t.getClassId(), t -> t));
        // 现在用学生与班级进行匹配,如果是班级号一致,认为这个学生是本班级的
        studentList.stream().forEach(h -> {
            if (noClassMap.containsKey(h.getClassesId())) {
                // System.out.println("该学生:" + h.getStuId() + "是有班级的");
            }
        });
    }
    复制代码
  5. 运行比较两者耗时情况

    耗时代码

    最终结果是:

    for双层循环方式耗时:80438ms

    Stream流方式耗时:80ms

同一个业务场景,二者处理结果相同,但耗时却是云泥之别,令人惊叹。

Stream在背后做了什么?

其实,我也不是很清楚,一起来学习吧。

知识忙去.PNG

如果一上来就了解最底层Stream是怎么实现的,这完全是和自己作对;你丫学《C语言程序设计》的时候,有学for(int i=0;i<n;i++)是怎么完成遍历的吗!

回答,肯定是没有呀。对一个知识的掌握,由浅入深,知其特性再探究原因,如果你非要一上来就看Stream源码,也行。我很期待哦,静静地看你表演。看你表演

Stream的分类

了解Stream原理之前,先要知道它的操作分类,因为Stream的操作分类就是实现高效迭代集合的原因之一。

操作分类

官方将 Stream 中的操作分为两大类:中间操作(Intermediate operations)和终结操作 (Terminal operations)。中间操作只对操作进行了记录,即只会返回一个流,不会进行计算操作,而终结操作是实现了计算操作。

中间操作又可以分为无状态(Stateless)与有状态(Stateful)操作,前者是指元素的处理不受之前元素的影响,后者是指该操作只有拿到所有元素之后才能继续下去。

终结操作又可以分为短路(Short-circuiting)与非短路(Unshort-circuiting)操作,前者是指遇到某些符合条件的元素就可以得到最终结果,后者是指必须处理完所有元素才能得到最终结果。

我们通常还会将中间操作称为懒操作,也正是由这种懒操作结合终结操作、数据源构成的处理管道(Pipeline),实现了 Stream 的高效。

Stream的特点

  1. 数据流从一头获取数据源,在流水线上依次对元素进行操作,当元素通过流水线,便无法再对其进行操作,可以重新在数据源获取一个新的数据流进行操作;

  2. 对Collection进行处理,一般会使用 Iterator 遍历器的遍历方式,这是一种外部迭代;

    而对于处理Stream,只要申明处理方式,处理过程由流对象自行完成,这是一种内部迭代,对于大量数据的迭代处理中,内部迭代比外部迭代要更加高效;

Stream的性能

那是不是Stream就能完全取代for方式,性能更优呢?也未必。

根据官方效率数据显示:

  1. 多核 CPU 服务器配置环境下,对比长度 100 的 int 数组的性能

    常规的迭代 <Stream 并行迭代 <Stream 串行迭代

  2. 多核 CPU 服务器配置环境下,对比长度 1.00E+8 的 int 数组的性能;

    Stream 并行迭代 < 常规的迭代 <Stream 串行迭代

  3. 多核 CPU 服务器配置环境下,对比长度 1.00E+8 对象数组过滤分组的性能;

    Stream 并行迭代 < 常规的迭代 <Stream 串行迭代

  4. 单核 CPU 服务器配置环境下,对比长度 1.00E+8 对象数组过滤分组的性能;

    常规的迭代 <Stream 串行迭代 <Stream 并行迭代

建议多使用Stream吧

按官方性能统计来看,使用Stream未必可以使得遍历性能更优,具体的要依赖数据量,即实际应用场景。

不过,在我们平时的业务开发中,我建议还是多使用Stream方式。效率是写代码的考虑因素,但不是绝对因素,随着技术的发展,执行效率一定会随着硬件发展而快速提高;对于写代码的人来说,代码一定要以简洁为原则,损失一点效率,换来的是高可读的代码,我觉得是非常值得的。

来源:https://juejin.cn/post/7057694629474336775

标签:班级,双层,Stream,迭代,学生,操作,stream,OUT
From: https://www.cnblogs.com/konglxblog/p/16756247.html

相关文章

  • 【动手实战】你真的会用 Stream ?来试试看!
    本文已参与「新人创作礼」活动,一起开启掘金创作之路。1.初始化数据以下所提到的内部Map即map1、map2,外部Map即mappublicclassStreamPractice{@Data......
  • Empire Breakout学习体会
    申明:本文为靶机EMPIRE:BREAKOUT学习笔记,相关操作仅在测试环境中进行,严禁任何危害网络安全的恶意行为。本文主要记录了一些关键知识点,仅供学习!一、安装说明靶机在https://ww......
  • 09-RabbitMQ核心API-Fanout Exchange
    FanoutExchange简介不处理路由键,只需要简单的将队列绑定到交换机上发送到交换机的消息都会被转发到与该交换机绑定的所有队列上Fanout交换机转发消息是最快的......
  • exploration plor,ploit — flow out ,weep
    explorationplor,ploit—flowout,weep为什么今天新学了个单词exploration很简单可以查出和explore有关联explorationn.探险,踏勘,探测助记:explore【探险......
  • 求求你们了,别再乱用 parallelStream 了,速度竟然比 Stream 还要慢!!
    parallelStream一定更快吗?大家都知道Stream分为顺序流和并行流:stream(顺序流)parallelStream(并行流)它们最大的区别就是parallelStream支持并行化处理,所以效率较stream(顺......
  • C++标准库iostream
    iostream标准库iostream是C++的标准库之一,为内置类型对象提供了输入输出支持,同时也支持文件的输入输出,封装的命名空间名称为std。C++的I/O发生在流中,流是字节序列。iost......
  • goroutine
    一、介绍goroutine是Go语言中的轻量级线程,用户态级别,由Go运行时(runtime)调度和管理,它比线程更加易用、高效和轻便每一个并发的执行单元叫作一个goroutine,Go程......
  • Two-Stream Convolutional Networks for Action Recognition in Videos论文精读
    Two-StreamConvolutionalNetworksforActionRecognitioninVideos论文精读大家好,今天我要讲的论文是一篇视频理解领域的开山之作,这是2014年发表在NIPS的一篇文章。这......
  • C艹 里 printf 和 cout 的区别总结
    1.printf里面打出%需要连着打出两次打出一次默认为格式标识符打出两次:2.当未完待续......
  • graylog OutputRouter 简单说明
    OutputRouter核心是基于stream以及消息获取到实际消息的外部输出,方便后续的存储以及处理,实现上依赖了OutputRegistry存储了MessageOutput与Stream的关系,可以用来方便......