java Stream编程笔记

文章目录

  • Stream
    • 介绍
      • 什么是 Stream?
    • Stream中间操作
      • 过滤操作(filter)
      • 映射操作(map)
      • 排序操作(sorted)
      • 截断操作(limit 和 skip)
    • Stream 的终止操作
      • forEach 和 peek
      • 聚合操作(reduce)
      • 匹配操作(allMatch、anyMatch 和 noneMatch)
      • 查找操作(findFirst 和 findAny)
      • 统计操作(count、max 和 min)

Stream

介绍

Java Stream 的主要作用有以下几个方面:

  • 简化集合操作:使用传统的 for 循环或迭代器来处理集合数据可能会导致冗长而复杂的代码。
  • 延迟计算:流式操作允许你在处理数据之前定义一系列的操作步骤,但只在需要结果时才会实际执行。这种延迟计算的特性意味着可以根据需要动态调整数据处理的操作流程,提升效率。
  • 并行处理:Java Stream 提供了并行流的支持,可以将数据分成多个块进行并行处理,从而充分利用多核处理器的性能优势,提高代码的执行速度。
  • 函数式编程风格:流式编程鼓励使用函数式编程的思想,通过传递函数作为参数或使用 Lambda 表达式来实现代码的简化和灵活性。

为什么使用流式编程可以提高代码可读性和简洁性

  • 声明式编程风格:流式编程采用了一种声明式的编程风格,你只需描述你想要对数据执行的操作,而不需要显式地编写迭代和控制流语句。

  • 链式调用:流式编程使用方法链式调用的方式,将多个操作链接在一起。每个方法都返回一个新的流对象,这样你可以像“流水线”一样在代码中顺序地写下各种操作,使代码逻辑清晰明了。

  • 操作的组合:流式编程提供了一系列的操作方法,如过滤、映射、排序、聚合等,这些方法可以按照需要进行组合使用。你可以根据具体的业务需求将这些操作串联起来,形成一个复杂的处理流程,而不需要编写大量的循环和条件语句。

  • 减少中间状态:传统的迭代方式通常需要引入中间变量来保存中间结果,这样会增加代码的复杂度和维护成本。而流式编程将多个操作链接在一起,通过流对象本身来传递数据,避免了中间状态的引入。

  • 减少循环和条件:流式编程可以替代传统的循环和条件语句的使用。

什么是 Stream?

Stream(流)是一个来自数据源的元素队列并支持聚合操作

  • 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
  • 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
  • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
  • 不可变性:Stream 是不可变的,它不会修改原始数据源,也不会产生中间状态或副作用。每个操作都会返回一个新的流对象,以保证数据的不可变性。
    和以前的Collection操作不同, Stream操作还有两个基础的特征:
  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

Stream中的操作大体可以分为两类

  • 中间操作:将流一层层的进行处理,并向下一层进行传递,如 filter map sorted等。
    中间操作又分为有状态(stateful)及无状态(stateless)
    • 有状态:必须等上一步操作完拿到全部元素后才可操作,如sorted
    • 无状态:该操作的数据不收上一步操作的影响,如filter map
  • 终止操作:触发数据的流动,并收集结果,如collect findFirst forEach等。终止操作又分为短路操作(short-circuiting)及非短路操作(non-short-circuiting)
    • 短路操作:会在适当的时刻终止遍历,类似于break,如anyMatch findFirst等
    • 非短路操作:会遍历所有元素,如collect max等

Stream中间操作

过滤操作(filter)

过滤操作(filter),它接受一个 Predicate 函数作为参数,用于过滤 Stream 中的元素。只有满足 Predicate 条件的元素会被保留下来,而不满足条件的元素将被过滤掉。

过滤操作的语法如下

Stream<T> filter(Predicate<? super T> predicate)

其中,T 表示 Stream 元素的类型,predicate 是一个函数式接口 Predicate 的实例,它的泛型参数和 Stream 元素类型一致,并且predicate返回的值必须是boolean类型,因为需要通过真假值判断是否要过滤该值。

使用过滤操作可以根据自定义的条件来筛选出符合要求的元素,从而对 Stream 进行精确的数据过滤。

下面是一个示例,演示如何使用过滤操作筛选出一个整数流中的大于三的数:

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
//        生成流式对象
//        Stream<Integer> stream = numbers.stream();List<Integer> list=numbers.stream().filter((x)->{return x>3;}  //lambda表达式 可简化成下面的写法
//                x->x>3).toList();System.out.println("number中大于3的数: "+list.toString());

映射操作(map)

映射操作(map),它接受一个 Function 函数作为参数,用于对 Stream 中的每个元素进行映射转换,生成一个新的 Stream。

映射操作的语法如下:

<R> Stream<R> map(Function<? super T, ? extends R> mapper)

其中,T 表示原始 Stream 的元素类型,R 表示映射后的 Stream 的元素类型,mapper 是一个函数式接口 Function 的实例,可以进行不同的映射操作.

下面是一个示例,演示如何使用映射操作将一个字符串流中的每个字符串转换为其长度:

        List<String> numbers = Arrays.asList("apple", "banana", "cherry");
//        生成流式对象
//        Stream<Integer> stream = numbers.stream();numbers.stream().map(String::length).forEach(System.out::println);

在这个示例中,我们首先创建了一个包含字符串的 Stream,并调用 map() 方法传入String::length,表示要将每个字符串转换为其长度。然后通过 forEach() 方法遍历输出结果。

注意: 映射操作可能引发空指针异常(NullPointerException),因此在执行映射操作时,应确保原始 Stream 中不包含空值,并根据具体情况进行空值处理。

排序操作(sorted)

排序操作(sorted)是 Stream API 中的一种常用操作方法,它用于对 Stream 中的元素进行排序。排序操作可以按照自然顺序或者使用自定义的比较器进行排序。

排序操作的语法如下:

Stream<T> sorted() Stream<T> sorted(Comparator<? super T> comparator)
  • 第一种语法形式中,sorted() 方法会根据元素的自然顺序进行排序。如果元素实现了 Comparable 接口并且具备自然顺序,那么可以直接调用该方法进行排序。

  • 第二种语法形式中,sorted(Comparator<? super T> comparator) 方法接受一个比较器(Comparator)作为参数,用于指定元素的排序规则。通过自定义比较器,可以对非 Comparable 类型的对象进行排序。

下面是一个示例,演示如何使用排序操作对一个字符串流进行排序:

        List<String> numbers = Arrays.asList("apple", "banana", "cherry");
//        生成流式对象
//        Stream<Integer> stream = numbers.stream();numbers.stream().sorted().forEach(System.out::println);

输出

apple
banana
cherry

注意: 排序操作可能会影响程序的性能,特别是对于大型数据流或者复杂的排序规则。因此,在实际应用中,需要根据具体情况进行权衡和优化,选择合适的算法和数据结构来提高排序的效率。

截断操作(limit 和 skip)

截断操作(limit和skip),用于在处理流的过程中对元素进行截断。

  1. limit(n):保留流中的前n个元素,返回一个包含最多n个元素的新流。如果流中元素少于n个,则返回原始流。
  2. skip(n):跳过流中的前n个元素,返回一个包含剩余元素的新流。如果流中元素少于n个,则返回一个空流。
    下面分别详细介绍这两个方法的使用。

注意: 在使用截断操作时需要注意流的有界性。如果流是无界的(例如 Stream.generate()),那么使用 limit() 方法可能导致程序陷入无限循环,而使用 skip() 方法则没有意义。

Stream 的终止操作

forEach 和 peek

forEach和peek都是Stream API中用于遍历流中元素的操作方法,它们在处理流的过程中提供了不同的功能和使用场景。

forEach: forEach是一个终端操作方法,它接受一个Consumer函数作为参数,对流中的每个元素执行该函数。forEach会遍历整个流,对每个元素执行相同的操作。

示例代码:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);

peek: peek是一个中间操作方法,它接受一个Consumer函数作为参数,对流中的每个元素执行该函数。与forEach不同的是,peek方法会返回一个新的流,该流中的元素和原始流中的元素相同。

示例代码:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> upperCaseNames = names.stream().map(String::toUpperCase).peek(System.out::println).toList();

聚合操作(reduce)

reduce和collect都是Stream API中用于聚合操作的方法,它们可以将流中的元素进行汇总、计算和收集。

reduce: reduce是一个终端操作方法,它接受一个BinaryOperator函数作为参数,对流中的元素逐个进行合并操作,最终得到一个结果。该方法会将流中的第一个元素作为初始值,然后将初始值与下一个元素传递给BinaryOperator函数进行计算,得到的结果再与下一个元素进行计算,以此类推,直到遍历完所有元素。

示例代码:

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);numbers.stream().reduce(Integer::sum).ifPresent(System.out::println);//输出结果15

在这个示例中,我们创建了一个包含整数的List,并通过stream()方法将其转换为流。然后使用reduce方法对流中的元素进行求和操作,将每个元素依次相加,得到结果15。

匹配操作(allMatch、anyMatch 和 noneMatch)

在 Stream API 中,allMatch、anyMatch 和 noneMatch 是用于进行匹配操作的方法,它们可以用来检查流中的元素是否满足特定的条件。

allMatch: allMatch 方法用于判断流中的所有元素是否都满足给定的条件。当流中的所有元素都满足条件时,返回 true;如果存在一个元素不满足条件,则返回 false。

anyMatch: anyMatch 方法用于判断流中是否存在至少一个元素满足给定的条件。当流中至少有一个元素满足条件时,返回 true;如果没有元素满足条件,则返回 false。

在这个示例中,我们创建了一个包含整数的 List,并通过 stream() 方法将其转换为流。然后使用 anyMatch 方法判断流中是否存在偶数。由于列表中存在偶数,所以返回 true。

noneMatch: noneMatch 方法用于判断流中的所有元素是否都不满足给定的条件。当流中没有元素满足条件时,返回 true;如果存在一个元素满足条件,则返回 false。

示例代码:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean allEven = numbers.stream().allMatch(n -> n % 2 == 0);
System.out.println(allEven); // 输出结果: false
boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0);
System.out.println(hasEven); // 输出结果: true
boolean noneNegative = numbers.stream().noneMatch(n -> n < 0);
System.out.println(noneNegative); // 输出结果: true

查找操作(findFirst 和 findAny)

在 Stream API 中,findFirst 和 findAny 是用于查找操作的方法,它们可以用来从流中获取满足特定条件的元素。

findFirst: findFirst 方法用于返回流中的第一个元素。它返回一个 Optional 对象,如果流为空,则返回一个空的 Optional;如果流非空,则返回流中的第一个元素的 Optional。

findAny: findAny 方法用于返回流中的任意一个元素。它返回一个 Optional 对象,如果流为空,则返回一个空的 Optional;如果流非空,则返回流中的任意一个元素的 Optional。在顺序流中,通常会返回第一个元素;而在并行流中,由于多线程的处理,可能返回不同的元素。

示例代码


List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Optional<String> first = names.stream().findFirst();
first.ifPresent(System.out::println); // 输出结果: AliceList<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> any = numbers.stream().filter(n -> n % 2 == 0).findAny();
any.ifPresent(System.out::println); // 输出结果: 2 或 4(取决于并行处理的结果)

统计操作(count、max 和 min)

在 Stream API 中,count、max 和 min 是用于统计操作的方法,它们可以用来获取流中元素的数量、最大值和最小值。

count: count 方法用于返回流中元素的数量。它返回一个 long 类型的值,表示流中的元素个数。

max: max 方法用于返回流中的最大值。

min: min 方法用于返回流中的最小值。它返回一个 Optional 对象,如果流为空,则返回一个空的 Optional;如果流非空,则返回流中的最小值的 Optional。

示例代码

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
long count = numbers.stream().count();
System.out.println(count); // 输出结果: 5Optional<Integer> max = numbers.stream().max(Integer::compareTo);
max.ifPresent(System.out::println); // 输出结果: 5Optional<Integer> min = numbers.stream().min(Integer::compareTo);
min.ifPresent(System.out::println); // 输出结果: 1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/140789.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【pytorch深度学习】torch-张量Tensor

torch-张量Tensor 文章目录 torch-张量Tensor1. 张量Tensor 1. 张量Tensor torch.tensor() # 创建一个标量&#xff08;0维张量&#xff09; scalar_tensor torch.tensor(3.14) # 创建一个向量&#xff08;1维张量&#xff09; vector_tensor torch.tensor([1, 2, 3]) # 创…

【FPGA】十进制计数器 | 实现 4-bit 2421 十进制计数器 | 有限状态机(FSM)

目录 Ⅰ. 实践说明 0x00 十进制计数器 0x01 有限状态机&#xff08;FSM&#xff09; Ⅱ. 实践部分 0x00 4-bit 2421 十进制计数器 Ⅰ. 实践说明 0x00 十进制计数器 十进制计数器是一种以十进制运算的计数器&#xff0c;从 0 数到 9&#xff0c;然后返回 0 状态。由于它需…

青少年编程学习 等级考试 蓝桥杯/NOC/GESP等比赛资料合集

一、博主愚见 在当今信息技术高速发展的时代&#xff0c;编程已经成为了一种必备的技能。随着社会对于科技人才的需求不断增加&#xff0c;青少年编程学习正逐渐成为一种趋势。为了更好地帮助青少年学习编程&#xff0c;提升他们的技能和素质&#xff0c;博主结合自身多年从事青…

如何使用CORS和CSP保护前端应用程序安全

前端应用在提供无缝用户体验方面起着核心作用。在当今互联网的环境中&#xff0c;第三方集成和API的普及使得确保强大的安全性至关重要。安全漏洞可能导致数据盗窃、未经授权访问以及品牌声誉受损。本文将向您展示如何使用CORS和CSP为您的网页增加安全性。 嗨&#xff0c;大家好…

大数据可视化数据大屏可视化模板【可视化项目案例-05】

🎉🎊🎉 你的技术旅程将在这里启航! 🚀🚀 本文选自专栏:可视化技术专栏100例 可视化技术专栏100例,包括但不限于大屏可视化、图表可视化等等。订阅专栏用户在文章底部可下载对应案例源码以供大家深入的学习研究。 🎓 每一个案例都会提供完整代码和详细的讲解,不…

半导体PLM解决方案助力企业提升竞争力 | 百世慧®

行业背景 半导体&#xff08;semiconductor&#xff09;指常温下导电性能介于导体与绝缘体之间的材料。 半导体产业主要涵盖集成电路、处理器、存储器、传感器及光电子设备等领域。产品则广泛应用在个人电脑、智能手机、平板电脑、汽车电子、医疗设备、工业控制等领域。 近些…

基于安卓android微信小程序的校园互助平台

项目介绍 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整…

Unity中Shader的间接光的产生Meta Pass

文章目录 前言Unity中Shader的间接光的产生Meta Pass&#xff0c;这也是属于全局光照 GI 的内容。主要实现像现实生活中&#xff0c;光线照到有颜色的物体后&#xff0c;该物体有反射出该颜色的光的效果。 一、我们先使用Unity自带的Shader看看间接光效果1、先按照如下设置搭建…

Android 中注解的使用

Android Support Library 从 19.1 版本开始引入了一个新的注解库&#xff0c;其中包含了很多的元注解&#xff0c;使用它们修饰我们的代码&#xff0c; 可以让我们提高程序的开发效率&#xff0c;让我们更早的发现问题。以及对代码施以规范&#xff0c;让代码更加有可读性。这篇…

8年经验之谈 —— 记一次接口压力测试与性能调优!

经验总结 1. 如果总的CPU占用率偏高&#xff0c;且基本都被业务线程占用时&#xff0c;CPU占用率过高的原因跟JVM参数大小没有直接关系&#xff0c;而跟具体的业务逻辑有关。 2. 当设置JVM堆内存偏小时&#xff0c;GC频繁会导致业务线程停顿增多&#xff0c;TPS下降&#xff…

人工智能如何彻底改变移动测试自动化

移动测试自动化在确保移动应用程序的质量和可靠性方面发挥着至关重要的作用。随着移动领域持续快速发展&#xff0c;测试方法需要跟上移动设备日益增长的复杂性和多样性。在过去几年&#xff0c;AI驱动的技术发展极大改变移动测试的自动化程度。特别是去年ChatGPT的横空出世&am…

基于SSM的考研图书电子商务平台的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

【机试题】编写一个Java函数,实现批量获取数据的功能

题目&#xff1a;编写一个Java函数&#xff0c;实现批量获取数据的功能&#xff08;BService.get(List ids)&#xff09;。具体要求如下&#xff1a; 1)提供一个函数BService.get(List ids)&#xff0c;支持最多传入100个id&#xff1b; 2)在BService.get((List ids)函数内部&a…

设计模式-中介者模式(Mediator)

设计模式-中介者模式&#xff08;Mediator&#xff09; 一、中介者模式概述1.1 什么是中介者模式1.2 简单实现中介者模式1.3 使用中介者模式的注意事项 二、中介者模式的用途三、中介者模式实现方式3.1 使用接口和类的方式3.2 使用抽象工厂模式的方式3.3 使用单例模式的方式 一…

链动2+1模式系统开发之区域代理深度解析

区域代理的保护机制&#xff1a;在链动商城系统里设定的代理有唯一性&#xff0c;每个省只有一个省代&#xff0c;每个市只有一个市代&#xff0c;每个区县只有一个区县代。这样也是保护每个代理的收益权益。 区域代理包含的权益类别&#xff1a;购物奖励折扣&#xff1b;区域实…

Python实现猎人猎物优化算法(HPO)优化XGBoost回归模型(XGBRegressor算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 猎人猎物优化搜索算法(Hunter–prey optimizer, HPO)是由Naruei& Keynia于2022年提出的一种最新的…

Marin说PCB之 PCB封装和原理图封装的藕断丝连

最近天气开始降温了&#xff0c;小编我不得不拿出珍藏多年的秋裤穿上了&#xff0c;就是走路不太方便&#xff0c;有点紧啊&#xff0c;可能是当时衣服尺码买小了吧&#xff0c;不可能是我吃胖了&#xff0c;这个绝对不可能。 话说小编我今年属实有点走霉运啊&#xff0c;下班和…

计网自顶向下(Web服务器+UDPping+邮件客户端)

目录 &#x1f416;前言 &#x1f33c;Web服务器(作业1) &#x1f333;过程 &#x1f333;解释 &#x1f525;代码 &#x1f33c;UDPping程序(作业2) &#x1f333;过程 &#x1f333;解释 Client Server 整体逻辑 &#x1f525;代码 &#x1f33c;邮件客户端(作业…

Sass 最基础的语法

把每个点最简单的部分记录一下&#xff0c;方便自己查找 官方文档链接 Sass 笔记 1. & 父选择器&#xff0c;编译后为父选择器2. : 嵌套属性3. $ 变量3.1 数据类型3.2 变量赋值3.3. 数组3.4. map 4. 算数运算符5. #{}插值语法5.1 可以在选择器或属性名中使用变量5.2 将有引…

SQL对数据进行去重

工作中使用SQL对数据进行处理计算时可能会遇到这样的问题&#xff1b;读取的表数据会有重复&#xff0c;或者我们关注的几个字段的数据会有重复&#xff0c;直接使用原表数据会引起计算结果不准或者做表连接时产生笛卡尔积。 本文记录使用SQL进行数据去重的几种算法。 distinc…