文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

【Java基础教程】(三十)Java新特性篇 · 第十讲: Stream流——释放流式编程的效率与优雅,狂肝万字只为透彻讲清 Stream流!~

2023-08-16 14:24

关注

在这里插入图片描述

Java的Stream流是在Java 8中引入的一种用于处理集合数据的功能强大且易于使用的工具,旨在简化集合框架的操作。它的设计目的是为了提供一种更简洁、更灵活和更可读的方式来处理集合数据。

在之前,我们通常使用迭代器或循环来遍历和操作集合元素,这种方式容易出错且代码冗长。Java 8通过引入Stream流来解决这个问题,提供了一种函数式编程风格的集合操作方法。

Stream流是对集合进行操作的高级抽象,可以将集合看作是一种源(source),而Stream表示这个源上进行的计算操作序列。 通过使用Stream API,我们可以以流水线方式处理数据,并进行各种转换和聚合操作。

在Java中,Stream流分为两种类型:

Stream流具有以下特点:

Stream流的实现原理主要基于迭代器和函数式编程的思想。在内部迭代的过程中,流通过一系列操作进行链式处理,将每个元素传递给下一个操作,并最终生成结果。

在并行流的情况下,流将输入数据分成多个小块,分配给不同的线程并行处理。处理完后,再合并结果并返回。

Stream流具有以下优点:

然而,Stream流也有一些缺点:

3.1 语法

Stream提供了两种类型的操作:中间操作和终端操作。中间操作用于链式调用,并可以有多个,而终端操作是触发计算的地方。

而使用Stream主要分为三个步骤:

3.2 常用API详解

Stream API提供了丰富的操作方法,可根据不同的需求灵活选择。常用的操作API有:

以下是一些Stream操作API详情列表:

类型方法作用
中间操作filter(Predicate)过滤符合条件的元素
map(Function)对每个元素应用转换函数
flatMap(Function)将每个元素转换成Stream对象,然后将所有的Stream连接成一个Stream
distinct()去除重复的元素
sorted([Comparator])排序元素,默认为自然排序
limit(n)截取指定数量的元素
skip(n)跳过指定数量的元素
peek(Consumer)对每个元素执行操作,不影响流中的其他元素
takeWhile(Predicate)从开头开始连续取元素满足指定条件,直到遇到不满足条件的元素
dropWhile(Predicate)从开头开始连续跳过元素满足指定条件,直到遇到不满足条件的元素
终结操作collect(Collector)将流转换为集合或其他数据结构
forEach(Consumer)遍历流中的元素,并对其执行操作
reduce(BinaryOperator)使用给定的二元操作符将元素归约成一个值
max([Comparator])找出流中的最大值
min([Comparator])找出流中的最小值
toArray()将流中的元素转换为数组
count()统计流中的元素数量
findFirst()返回满足条件的第一个元素
findAny()返回任意满足条件的元素
anyMatch(Predicate)判断流中是否存在任意一个元素满足给定条件
allMatch(Predicate)判断流中所有元素是否都满足给定条件
noneMatch(Predicate)判断流中是否没有任何元素满足给定条件

3.3 案例

下面是一个简单的Java程序,演示了上述所有方法的使用:

import java.util.Arrays;import java.util.List;import java.util.stream.Collectors;public class StreamOperationsDemo {    public static void main(String[] args) {        // 创建一个包含整数的集合        List numbers = Arrays.asList(1, 2, 3, 4, 5, 1, 2, 3, 4, 5);        // filter: 过滤掉大于3的元素        List filteredList = numbers.stream()                .filter(num -> num <= 3)                .collect(Collectors.toList());        System.out.println("Filtered List: " + filteredList);        // map: 将每个元素乘以2        List mappedList = numbers.stream()                .map(num -> num * 2)                .collect(Collectors.toList());        System.out.println("Mapped List: " + mappedList);                // flatMap: 将每个元素转换成Stream对象,然后将所有的Stream连接成一个Stream        List words = Arrays.asList("Hello", "World");        List flatMappedList = words.stream()                .flatMap(word -> Arrays.stream(word.split("")))                .collect(Collectors.toList());        System.out.println("FlatMapped List: " + flatMappedList);        // distinct: 去除重复的元素        List distinctList = numbers.stream()                .distinct()                .collect(Collectors.toList());        System.out.println("Distinct List: " + distinctList);        // sorted: 对元素进行排序        List sortedList = numbers.stream()                .sorted()                .collect(Collectors.toList());        System.out.println("Sorted List: " + sortedList);        // limit: 截取指定数量的元素        List limitedList = numbers.stream()                .limit(3)                .collect(Collectors.toList());        System.out.println("Limited List: " + limitedList);        // skip: 跳过指定数量的元素        List skippedList = numbers.stream()                .skip(3)                .collect(Collectors.toList());        System.out.println("Skipped List: " + skippedList);        // peek: 对每个元素执行操作,不影响流中的其他元素        List peekedList = numbers.stream()                .peek(num -> System.out.println("Peeking element: " + num))                .collect(Collectors.toList());        // takeWhile: 从开头开始连续取元素满足条件,直到遇到不满足条件的元素        List takenList = numbers.stream()                .takeWhile(num -> num < 4)                .collect(Collectors.toList());        System.out.println("Taken List: " + takenList);        // dropWhile: 从开头开始连续跳过元素满足条件,直到遇到不满足条件的元素        List droppedList = numbers.stream()                .dropWhile(num -> num < 4)                .collect(Collectors.toList());        System.out.println("Dropped List: " + droppedList);        // collect: 将流转换为集合或其他数据结构        List collectedList = numbers.stream()                .collect(Collectors.toList());        System.out.println("Collected List: " + collectedList);        // forEach: 遍历流中的元素,并对其执行操作        numbers.stream()                .forEach(System.out::println);        // reduce: 使用给定的二元操作符将元素归约成一个值        int sum = numbers.stream()                .reduce(0, Integer::sum);        System.out.println("Sum: " + sum);        // max: 找出流中的最大值        int max = numbers.stream()                .max(Integer::compare)                .orElse(-1);        System.out.println("Max: " + max);        // min: 找出流中的最小值        int min = numbers.stream()                .min(Integer::compare)                .orElse(-1);        System.out.println("Min: " + min);        // toArray: 将流中的元素转换为数组        Integer[] array = numbers.stream()                .toArray(Integer[]::new);        System.out.println("Array: " + Arrays.toString(array));        // count: 统计流中的元素数量        long count = numbers.stream()                .count();        System.out.println("Count: " + count);        // findFirst: 返回满足条件的第一个元素        int first = numbers.stream()                .findFirst()                .orElse(-1);        System.out.println("First: " + first);        // findAny: 返回任意满足条件的元素        int any = numbers.stream()                .findAny()                .orElse(-1);        System.out.println("Any: " + any);        // anyMatch: 判断流中是否存在任意一个元素满足给定条件        boolean anyMatch = numbers.stream()                .anyMatch(num -> num % 2 == 0);        System.out.println("Any Match: " + anyMatch);        // allMatch: 判断流中所有元素是否都满足给定条件        boolean allMatch = numbers.stream()                .allMatch(num -> num % 2 == 0);        System.out.println("All Match: " + allMatch);        // noneMatch: 判断流中是否没有任何元素满足给定条件        boolean noneMatch = numbers.stream()                .noneMatch(num -> num > 10);        System.out.println("None Match: " + noneMatch);    }}

这个程序演示了如何使用Stream的中间操作和终端操作。

程序的运行结果如下:

Filtered List: [1, 2, 3, 1, 2, 3]Mapped List: [2, 4, 6, 8, 10, 2, 4, 6, 8, 10]FlatMapped List: [H, e, l, l, o, W, o, r, l, d]Distinct List: [1, 2, 3, 4, 5]Sorted List: [1, 1, 2, 2, 3, 3, 4, 4, 5, 5]Limited List: [1, 2, 3]Skipped List: [4, 5, 1, 2, 3, 4, 5]Peeking element: 1Peeking element: 2Peeking element: 3Peeking element: 4Peeking element: 5Peeking element: 1Peeking element: 2Peeking element: 3Peeking element: 4Peeking element: 5Taken List: [1, 2, 3]Dropped List: [4, 5, 1, 2, 3, 4, 5]Collected List: [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]1234512345Sum: 30Max: 5Min: 1Array: [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]Count: 10First: 1Any: 1Any Match: trueAll Match: falseNone Match: true

Stream流广泛应用于数据处理、集合操作、并行计算等场景。它可以使代码更简洁、易读和具有可维护性,同时充分发挥多核处理器的计算能力。如下:

例如,对于一个电商平台的订单数据,我们可以使用流来实现以下功能:

要使用流,首先需要从数据源创建一个流,然后通过一系列的中间操作和终端操作来对流进行处理和操作。

在使用流时,可以注意以下几点优化技巧:

并行流(ParallelStream)允许在多线程环境下并发地执行操作,从而提高处理大数据集的效率。

ParallelStream类在Java中没有特有的方法。它与普通的Stream类具有相同的操作方法,可以使用 filtermapflatMapdistinctsortedlimitskippeek 等方法。这些方法可以在并行流上执行,并发地处理数据。并行流会自动将数据分成多个部分,并在多个线程上同时进行处理,加快了处理速度。

需要注意的是,在使用并行流时,应该要注意线程安全和性能问题。如果并行执行的操作具有共享状态、副作用或依赖于元素之间的顺序,那么可能会导致不正确的结果。并行流适用于对大量元素进行计算密集型操作,但并不适用于有状态或依赖前后元素的操作。因此,在使用并行流时,需要确保操作的可靠性,并在必要时使用同步措施来保证线程安全。

除了以上普通的Stream操作方法,在并行流中还可以使用.parallel().sequential()方法切换并行流和顺序流的操作模式。.parallel()方法将流转换为并行流,允许并发地对元素进行操作。而.sequential()方法则将并行流转回为顺序流,仅使用单线程顺序地处理元素。

Java Stream流为我们提供了一种简洁而强大的方式来操作数据集合。它具有许多优点,如简化操作、惰性求值和并行处理。同时也有一些缺点,如学习成本稍高和可读性稍差。然而,在正确使用和优化Stream的情况下,可以极大地提高代码的可读性和维护性,并实现更高效的数据处理与计算。

通过使用流,我们可以以更直观、简洁的方式对数据进行处理和操作,并发挥多核处理器的计算能力。

然而,使用流也需要注意数据量、性能和适用场景等因素。最重要的是根据具体情况选择合适的流类型,并根据实际需求合理组合流的操作,以实现更高效、可读性更好的代码。


温习回顾上一篇(点击跳转)《【Java基础教程】(二十九)Java新特性篇 · 第九讲:函数式接口——概念及优缺点、语法形式及实战技巧、 内置函数式接口与应用场景~》

继续阅读下一篇(点击跳转)《【Java基础教程】(三十一)常用类库篇 · 第一讲:Optional类——解锁Java的Optional操作,消灭那些隐匿的空指针,还程序世界一个安稳!~》

来源地址:https://blog.csdn.net/LVSONGTAO1225/article/details/131380347

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯