Java8 Stream流式编程整理

本文介绍了Java8的Stream流特性,包括其工作原理、不同类型的Stream流、处理顺序、性能优化、数据流复用、补充操作以及并行流的使用。通过实例代码展示了如何利用Stream简化集合操作,提高性能,并探讨了并行流在处理大量数据时的性能优势。同时,文章提到了Stream的延迟执行特性和中间操作顺序对性能的影响,以及如何通过调整操作顺序来优化执行效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

Java8上线很多年了,Stream流基本上是Java8的新特性里面最清爽的一个功能。
有了Stream流,操作集合可以告别繁琐的for循环,简化代码、操作集合可以肆意妄为的获取自己想要的数据、而且操作拥有大量数据的集合的性能也有强大的提升。
学习的路上,做笔记,一起了解一下。



一:Stream 流是如何工作的

流表示包含一系列元素的集合,我们可以对集合进行不同类型的操作,如下


//对象流
        List<String> myList = Arrays.asList("a1", "b1", "e1", "d1", "C1", "C1");

        myList.stream()
                .filter(c -> c.startsWith("C"))//过滤
//              .filter(s -> s.startsWith("a"))
                .map(String::toLowerCase)//对集合内元素进行操作
                .sorted()//排序
                .forEach(System.out::println);//遍历对元素进行操作
        /*
         * c1
         * c1
         * */

上面的一个简单的流处理。涉及到两个基本的操作:中间操作【filter、map、sort】和终端操作【forEach】

①:中间操作会再次返回一个流,所以,我们可以链接多个中间操作,注意这里是不用加分号的。上图中的 filter 过滤, map 对象转换, sorted 排序,就属于中间操作。
②:终端操作是对流操作的一个结束动作,一般返回 void 或者一个非流的结果。上图中的 forEach循环 就是一个终止操作。

二、不同类型的 Stream 流

我们可以从各种数据源中创建 Stream 流,其中以 Collection 集合最为常见。如 List 和 Set 均支持 stream() 方法来创建顺序流或者是并行流

并行流是通过多线程的方式来执行的,它能够充分发挥多核 CPU 的优势来提升性能。本文在最后再来介绍并行流,我们先讨论顺序流

像第一部分代码演示的就是一个常规的对象流,除了常规的对象流之外Java 8还附带了一些特殊类型的流,用于处理原始数据类型 int, long以及 double。对应的IntStream, LongStream还有 DoubleStream。

其中, IntStreams.range()方法还可以被用来取代常规的 for 循环, 如下所示:

        IntStream.range(1, 4).forEach(System.out::println);
        // 相当于 for (int i = 1; i < 4; i++) {}

原始类型流和常规对象流有什么区别呢?
一个部分函数式接口名不一样,功能相同。二个比较好用的在于原始类型流支持额外的终端聚合操作,sum()以及average(),如下所示:

//额外的终端聚合操作, sum()以及 average()
        Arrays.stream(new int[]{
   
   1, 2, 3})
                .map(n -> 2 * n + 1)//对数值中的每个对象执行 2*n + 1 操作
                .average()// 求平均值
                .ifPresent(System.out::println);// 如果值不为空,则输出

eg:应用场景
常规对象流和原始类型流互相转换,这个时候,中间操作 mapToInt(),mapToLong()和mapToDouble()和mapToObj()就派上用场了

//常规对象流转换为原始类型流
        Stream.of("a1", "b1", "e1", "d1", "C1", "C1")
                .map(s -> s.substring(1))
//                .map(Integer::parseInt)
                .mapToInt(Integer::parseInt)
                .max()
                .ifPresent(System.out::println);// 如果值不为空,则输出

        //常规对象流转换为原始类型流
        IntStream.range(1, 4)
                .mapToObj(i -> "a" + i)
                .forEach(System.out::println);// 相当于 for (int i = 1; i < 4; i++) {}

三、Stream 流的处理顺序

大致了解不同类型的Stream流之后,再了解一下数据流的执行顺序。在此之前需要了解流的中间操作另外一个特性------延迟性。先上代码再做总节

下面是一个没有终端操作的实例代码

  Stream.of("a1", "b1", "e1", "d1", "C1", "C1")
                .filter(s -> {
   
   
                    System.out.println("filter:" + s);
                    return true;
                });

执行这段代码会有什么结果呢?什么结果也没有! 因为:当且仅当存在终端操作时,中间操作才会被执行。

下面来验证一下

Stream.of("a1", "b1", "e1", "d1", "C1", "C1")
                .filter(s -> {
   
   
                    System.out.println("filter:" + s);
                    return true;
                })
                .forEach(s -> System.out.println("Foreach:" + s));

执行本次代码,控制台会输出

filter:a1
Foreach:a1
filter:b1
Foreach:b1
filter:e1
Foreach
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值