• 关于Java8 stream的相关使用及解析



    前言

    蓦然回首,有好久不能够在休息日里去学习新知识、新技能,也好久没有把遇到的问题记录到博客中。往往只能够在工作日时,做好业务上的实现。今年求职过程中,竟然被问到了Java9,我甚至连Java8的函数式编程都没掌握明白。入职某药企,发现在其项目代码中大篇幅的使用函数式编程,左思右想,决定写记录一下Java8中stream的特性,增强自己的记忆力。
    在这里插入图片描述

    一、Stream是什么?

    首先,Stream作为Java8的一大亮点,它与java.io包里的InputStream和OutputStream是完全的两个概念。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作(bulk data operation)。
    Stream API 借助于同样新出现的 Lambda 表达式,而且使用并发模式,极大的提高编程效率和程序可读性。
    另外,Stream有几个特性:
    1.Stream不改变数据源,会产生一个新的集合
    2.Stream不存储数据,只是按照特定规则进行计算
    3.Stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行

    二、Stream使用

    1.源码

    在这里插入图片描述

    从源码中不难看出,Stream提供的方法有很多,缩短时间,提取其中常用的几种方法进行说明。源码在java.util.stream.Stream 目录下,有时间的同学可以去研究研究。

    1.collect

    代码如下(示例):

        @Test
        public void test1(){
            Integer[] numArr = {1, 2, 3, 4, 5};
            List<Integer> list = Stream.of(numArr).collect(Collectors.toList());
            log.info("list:{}",JSONObject.toJSONString(list));
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    将流转换为其他形式,接收一个Collect接口实现。
    Collectors.toList()是Java 8 流的新类 java.util.stream.Collectors 实现了 java.util.stream.Collector 接口,同时又提供了大量的方法对流 ( stream ) 的元素执行 map and reduce 操作,或者统计操作。
    Collectors.toList() 是将流中的所有元素导出到一个列表( List )中。

    2.map / flatMap 映射转换

    代码如下(示例):

      List<User> userList = new ArrayList<>();
                userList.add(new User(3, "张一鸣"));
                userList.add(new User(1, "zym"));
                userList.add(new User(2, "zhangyiming"));
                // 提取User的Name转成List集合
                List<String> nameList = userList.stream()
                        .map(User::getName).collect(Collectors.toList());
                System.out.println(nameList);   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    该方法将list泛型对象中某一个属性提取,重新汇入一个list对象接收。输出为所有name。


    3.filter过滤属性

    代码如下(示例):

      List<Integer> numList = Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6});
            // 取出集合中的所有偶数
            numList = numList.stream()
                    .filter(num -> num % 2 == 0).collect(Collectors.toList());
            System.out.println(numList ); 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    在项目代码中也经常会使用到过滤属性,其目的是将当前list中,筛选出符合条件的参数,生成一个新Stream。

    4.reduce 聚合

     		// 字符串拼接
            String[] arr = {"a", "b", "c", "d"};
            String content = Stream.of(arr).reduce("", String::concat);
            System.out.println(content);        //  输出 abcd
    
            // 求和, 需要一个起始参数值
            int sum = Stream.of(1, 2, 3, 4, 5, -2).reduce(0, Integer::sum);
            System.out.println(sum);            // 输出 13
    
            // 找最大值
            int maxNum = Stream.of(1, 3, 5, -2, 0).reduce(Integer::max).get();
            System.out.println(maxNum);        // 输出 5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述
    BinaryOperator类表示对两个相同类型的操作数的运算,并产生与该操作数相同类型的结果,进入BinaryOperator源码查看,发现@FunctionalInterface,定义函数式接口,所以reduce的参数就一目了然了。
    在这里插入图片描述

    4.sorted 排序

    在药企项目中发现一个比较奇怪的写法,查询库表把所有信息查询出来,通过Stream进行相关的条件过滤,利用sorted进行排序 返回至前台,我不太确定这样做是否能够提高性能,日后有时间出一篇性能比较。
    在这里插入图片描述
    在这里插入图片描述
    基本DB层的数据拿过来后,利用Stream相关方法进行了过滤、分组、去重、排序。

    代码如下(示例):

       Integer[] numArr = {2, 3, 1, 5, 0 ,8};
            List<Integer> numList = Stream.of(numArr)
                    .sorted().collect(Collectors.toList());
            System.out.println(numList);        // 输出[0, 1, 2, 3, 5, 8]
    
            // 反向排序
            numList = Stream.of(numArr)
                    .sorted(Comparator.reverseOrder()).collect(Collectors.toList());
            System.out.println(numList);     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    总结

    以上就是关于Stream相关用法,时间关系,很多源码解读及运行过程未做详细说明,只提取了几种常用的方法给大家参考。同时,在使用性能上似乎存在了问题,关于Stream的性能问题我也阅读了很多文章,等日后有时间做一次性能比较后再进行补充。
    不足之处,请批评指正
    在这里插入图片描述

  • 相关阅读:
    Spark 平障录
    白杨SEO:SEO转型系列之十一,传统SEO从业人员如何转行社群运营/营销?
    源码级深度理解 Java SPI
    从外到内理解c++引用
    新品发布:立仪科技发布嵌入式低功耗光谱共焦E系列
    gRPC简介
    前端CSS射门动画-为梅西最后一届世界杯加油
    女朋友问我深浅copy到底是什么?
    力扣OJ(601-800)
    UBOOT编译--- make xxx_deconfig过程详解(一)
  • 原文地址:https://blog.csdn.net/goGoing_/article/details/125459031