Java基础之Stream的使用078

news2024/12/23 13:51:19

1. Stream 的使用

Stream 是什么?

Stream 是数据渠道,用于操作数据源(数组、集合等)所生成的元素序列。

Java8两大最为重要的改变就是 Lambda表达式Stream API,这两种改变的引入带来的是新的抽象方式 (函数式编程),面向对象编程是对数据进行抽象,而函数式编程是对行为进行抽象

Stream 是 Java8 中处理集合的关键抽象概念,可以指定对集合进行的操作,可以执行复杂的查找、过滤、映射数据等操作,Stream API 提供了一种高效且易于使用的处理数据的方式。


四个必须要知道的内置函数接口

  1. 消费型接口: Consumer<T> void accept(T t) 有参数,无返回值的抽象方法;
  2. 供给型接口: Supplier <T> T get() 无参有返回值的抽象方法;
  3. 断定型接口: Predicate<T> boolean test(T t) 有参,但是返回值类型是固定的boolean;
  4. 函数型接口: Function<T,R> R apply(T t) 有参有返回值的抽象方法;
// 消费接口定义
Consumer<Student> greeter = (p) -> System.out.println("Hello, " + p.firstName);
// 消费
greeter.accept(new Student("Luke", "Skywalker"));
复制代码
// 供给接口定义
Supplier<Student> supplier = Student::new;
// 供给
supplier.get();
复制代码
// 断定型接口定义
Predicate<String> predicate = (s) -> s.length() > 0;
// 断定
predicate.test("s");              // true
predicate.test("");     // false
复制代码
// 函数型接口定义
Function<String, Integer> toInteger = Integer::valueOf;
Function<String, String> backToString = toInteger.andThen(String::valueOf);
// 应用
backToString.apply("123");     // "123"
复制代码


Stream 的使用分为三个步骤

  1. 创建Stream (使用数据源可以是集合、数组来获取流)
  2. 中间操作 (对数据源的数据进行处理)
  3. 终止操作 (先执行中间操作产生结果后终止流,之后不能再使用该流)

惰性求值

中间操作不会执行任何的处理,而是在终止操作时一次性全部处理,这就是惰性求值

// 像这样的代码并未做什么实际工作
lists.stream().filter(x -> x != 1)
复制代码
// 像这种有终止操作的代码才会产生新值
List<Integer> list1 = list.parallelStream().filter(x -> x != 1).collect(Collectors.toList());
复制代码

1.1 创建 Stream 的方式

集合创建

  1. 顺序流:使用顺序方式遍历,每个item读完之后再读下一个item
  2. 并行流:使用并行遍历,将数据分为多个段,各个段的数据都在不同线程下处理

在多核计算机的情况下理论上并行流会比顺序流快上一倍左右

① 顺序执行:default Stream<E> stream() 返回一个顺序流

// 将list列表通过stream()生一个流过滤1最后打印
List<Integer> list1 = list.stream().filter(x -> x != 1).collect(Collectors.toList());
复制代码

② 并行执行:default Stream<E> parallelStream() 返回一个并行流

List<Integer> list1 = list.parallelStream().filter(x -> x != 1).collect(Collectors.toList());
复制代码

数组创建

通过Arrays静态方法获取数组流:static <T> Stream<T> stream(T[] array)

// 将array数组通过Arrays的静态方法生一个流过滤1最后打印
Arrays.stream(array).filter(x -> x != 1).forEach(System.out::println);
复制代码

Stream创建

通过调用Stream类的静态方法创建流 (注意后两个生成的是无限流)

① 通过显示值:public static<T> Stream<T> of(T... values)

// 通过显示值1,2,3,4生成一个流过滤掉1最后打印
Stream.of(1,2,3,4).filter(x -> x != 1).forEach(System.out::println);
复制代码

② 通过迭代:public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)

// 从0开始迭代每次加1生成一个无限流通过limit限制前十位最后打印
Stream.iterate(0, x -> x + 1).limit(10).forEach(System.out::println);
复制代码

③ 通过生成:public static<T> Stream<T> generate(Supplier<T> s)

// 通过Math的随机数函数生成一个无限流通过limit限制前五位最后打印
Stream.generate(Math::random).limit(5).forEach(System.out::println);
复制代码

1.2 中间操作

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

接收Lambda,从流中排除某些元素;

List<Integer> list = Arrays.asList(1,2,3,4);

// filter中传入一个判定型接口Predicate过滤掉遍历这个集合是返回false的结果
List<Integer> list1 = list.stream().filter(x -> x != 1).collect(Collectors.toList());

list1.forEach(System.out::print); // 234
复制代码

Stream<T> distinct();

筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素;

List<Integer> nums = Arrays.asList(1,1,2,3,4);
// 去重
nums.stream().distinct().forEach(System.out::print); // 1234
复制代码

Stream<T> limit(long maxSize);

截断流,使其元素不超过给定数量

// 通过Math的随机数函数生成一个无限流通过limit限制前五位最后打印
Stream.generate(Math::random).limit(5).forEach(System.out::println);
复制代码

Stream<T> skip(long n);

跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补

List<Integer> nums = Arrays.asList(1,1,2,3,4);
// 去重
nums.stream().skip(2).forEach(System.out::print); // 234
复制代码

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

接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

List<Integer> nums = Arrays.asList(1,1,2,3,4);
// 通过map对每个元素进行类型转换
List<Long> collect = nums.stream().map(Long::valueOf).collect(Collectors.toList());
复制代码

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

接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

// 合并多个流
List<Integer> result= Stream.of(Arrays.asList(1,3),Arrays.asList(5,6)).flatMap(Collection::stream).collect(Collectors.toList());
复制代码

Stream<T> sorted();

产生一个新流,其中按自然顺序排序

List<Integer> nums = Arrays.asList(8,6,7,3);
// 自然排序
nums.stream().sorted().forEach(System.out::print); // 3678
复制代码

Stream<T> sorted(Comparator<? super T> comparator);

产生一个新流,其中按比较器顺序排序

List<Integer> nums = Arrays.asList(8,6,7,3);
// 比较器排序
nums.stream().sorted((x,y) -> (y-x)).forEach(System.out::print); // 8763
复制代码

1.3 终止操作

boolean allMatch(Predicate<? super T> predicate);

检查是否匹配所有元素

List<Integer> nums = Arrays.asList(1,1,7,3);
// 检查是否集合里面的元素都等于1
System.out.println(nums.stream().allMatch(x -> x == 1)); // false
复制代码

boolean anyMatch(Predicate<? super T> predicate);

检查是否至少匹配一个元素

List<Integer> nums = Arrays.asList(1,1,7,3);
// 检查是否集合里面的元素有等于1的
System.out.println(nums.stream().anyMatch(x -> x == 1)); // true
复制代码

boolean noneMatch(Predicate<? super T> predicate);

检查是否没有匹配所有元素

List<Integer> nums = Arrays.asList(1,1,7,3);
// 检查是否集合里面的元素都不等于1
System.out.println(nums.stream().noneMatch(x -> x == 1)); // false
复制代码

Optional<T> findFirst();

返回第一个元素

List<Integer> nums = Arrays.asList(1,1,7,3);
// 拿到集合第一个元素用Optional存储可以通过get取出来
System.out.println(nums.stream().findFirst()); // Optional[1]
System.out.println(nums.stream().findFirst()); // 1
复制代码

Optional<T> findAny();

返回当前流中的任意元素

List<Integer> nums = Arrays.asList(1,1,7,3);
// 拿到集合任意元素用Optional存储可以通过get取出来
System.out.println(nums.stream().findFirst()); // Optional[1]
System.out.println(nums.stream().findFirst()); // 1
复制代码

long count();

返回流中元素总数

List<Integer> nums = Arrays.asList(3,7,3);
// 集合大小
System.out.println(nums.stream().count()); // 3
复制代码

Optional<T> max(Comparator<? super T> comparator);

返回流中最大值

List<Integer> nums = Arrays.asList(3,7,3);
// 返回比较器下的最大值用Optional存储通过get取出(注意这里的比较器是从大到小排序)
System.out.println(nums.stream().max((x, y) -> (y - x)).get()); // 3
复制代码

Optional<T> min(Comparator<? super T> comparator);

返回流中最小值

List<Integer> nums = Arrays.asList(3,7,3);
// 返回比较器下的最小值用Optional存储通过get取出(注意这里的比较器是从大到小排序)
System.out.println(nums.stream().min((x, y) -> (y - x)).get()); // 7
复制代码

void forEach(Consumer<? super T> action);

内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反,Stream API 使用内部迭代)

List<Integer> nums = Arrays.asList(3,7,3);
// 内部迭代
nums.stream().forEach(System.out::print); // 373
复制代码

Optional<T> reduce(BinaryOperator<T> accumulator);

可以将流中元素反复结合起来,得到一个值。返回 T

List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
// 将集合的值变成double类型并抹个零通过reduce反复结合即相加得到总和
double bill = costBeforeTax.stream().map((cost) -> 0.1 * cost).reduce(Double::sum).get();
System.out.println(bill); // 150.0
复制代码

T reduce(T identity, BinaryOperator<T> accumulator);

可以将流中元素反复结合起来,得到一个值。返回 Optional<T>

double bill = 100.0;
List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
// 跟上面的比就是多一个初始值在反复结合
bill = costBeforeTax.stream().map((cost) -> 0.1 * cost).reduce(bill, Double::sum);
System.out.println(bill); // 250.0
复制代码

<R, A> R collect(Collector<? super T, A, R> collector);

将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法

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

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

相关文章

目标检测之Fast RCNN概述

基本原理 Fast Rcnn主要步骤为 利用SR算法生成候选区域利用VGG16网络进行特征提取利用第一步生成的候选区域在特征图中得到对应的特征矩阵利用ROI pooling将特征矩阵缩放到相同大小并平展得到预测结果 相对于RCNN的优化 主要有三个改进 不再将每一个候选区域依次放入CNN网络…

【基于通道-空间注意的高分辨率锐化】

Channel–spatial attention-based pan-sharpening of very high-resolution satellite images &#xff08;基于通道-空间注意的很高分辨率卫星影像全色锐化&#xff09; 全色锐化处理旨在生成新的合成输出图像&#xff0c;其保留全色的空间细节和多光谱图像输入的光谱细节。…

【服务器端程序的演进过程】

目录 1 服务器端程序的演进过程 阶段一:静态服务器 阶段二:普通动态服务器 阶段三: 以用户共享内容为主的互联网生态 阶段四: 微服务时代(有高并发需求或特征的网站) 2 Java服务器项目分类 3 微服务概述 3.1 什么是微服务 3.2 为什么需要微服务 3.3 怎么搭建微服务项…

C#获取计算机详细的软件和硬件信息

利用System.Management提供的类可以用于读取本地计算机设备的各种数据&#xff0c;包括操作系统、软件、硬件的各种详细信息&#xff0c;内容很丰富。 System.Management的命名空间下&#xff0c;ManagementObjectSearcher类用于查询特定类型的设备&#xff0c;ManagementObjec…

转行做“程序员”很难?这里有几个建议...

“是什么&#xff1f;为什么&#xff1f;怎么样&#xff1f;”的灵魂三连问在我们生活中比比皆是&#xff0c;目的是为了清晰思考和看到事物的本质。对于编程学习也是一样&#xff0c;需要带着疑问从本质上去学习编。 本人是某985高校的本硕连读&#xff0c;非计算机科班出身&…

利器 | AppCrawler 自动遍历测试实践(三):动手实操与常见问题汇总

1080469 14.7 KB 上两篇文章介绍了自动遍历的测试需求、工具选择和 AppCrawler 的环境安装、启动及配置文件字段基本含义&#xff0c;这里将以实际案例更加细致的说明配置文件的用法和一些特殊场景的处理。 下面我们继续之前的例子&#xff0c;在雪球搜索框输入搜索内容后的页面…

CloudFlare系列--功能介绍与常用配置

原文网址&#xff1a;CloudFlare系列--功能与特性的介绍_IT利刃出鞘的博客-CSDN博客 简介 本文介绍CloudFlare的功能与常用的配置。 功能介绍 CloudFlare是世界最强的网络服务商。它可以提供如下服务&#xff1a; 防御DDoS攻击 世界最强防御DDos攻击的厂商。域名注册 世界最…

JavaWeb语法四:多线程案例

目录 1.单例模式 1.1&#xff1a;饿汉模式 1.2&#xff1a;懒汉模式 2.阻塞式队列 2.1:生产者消费者模型 2.2&#xff1a;阻塞队列的模拟实现 3.线程池 3.1&#xff1a;标准库中的线程池 3.2&#xff1a;模拟实现线程池 前言&#xff1a;前一篇我们讲了线程不安全的原因…

SAP UI5 里 FlexBox 的使用方法

ScrollContainer 的使用方式&#xff1a; ScrollContainer 是一个控件&#xff0c;可以在有限的屏幕区域内显示任意内容&#xff0c;并提供滚动以使所有内容都可访问。注意&#xff0c;为了避免影响用户使用体验&#xff0c;不要嵌套沿相同方向滚动的滚动区域。例如&#xff…

【LaTex】基础语法框架快速入门教程——Tex live+TexStudio简要安装及使用教程

0. 引言 LaTeX对于论文排版有着巨大的便利&#xff0c;并且对于参考文献的引用也十分方便&#xff0c;不会出现使用word引用参考文献一旦更改文献引用顺序&#xff0c;就必须全部改编号的情况。这里记录一下如何从0开始学习使用LaTeX书写论文。 1. 软件安装&环境配置 1.…

Qt中实例化一个函数变量时加不加括号的区别,以及括号中的this的使用

一、设计一个测试小程序 废话不多说&#xff0c;直接上代码。 main.h函数就不多说了&#xff0c;没改动。直接上mainwindow.h&#xff0c;也没改动。看mainwindow.cpp的内容。 #include "mainwindow.h" #include "ui_mainwindow.h" #include "test.…

机器学习算法基础——KNN算法

KNN (K-Nearest Neighbor)–K近邻分类算法 • 为了判断未知实例的类别&#xff0c;以所有已知类别的实例作为参照选择参数K • 计算未知实例与所有已知实例的距离 • 选择最近K个已知实例 • 根据少数服从多数的投票法则(majority-voting)&#xff0c;让未知实例归类为K个最邻…

Zerobot僵尸网络出现了新的漏洞利用和功能

©网络研究院 Zerobot DDoS僵尸网络已经获得了重大更新&#xff0c;扩展了其针对更多互联网连接设备和扩展网络的能力。 微软威胁情报中心 (MSTIC)正在以DEV-1061的名称跟踪持续的威胁&#xff0c;名称为未知、新兴或发展中的活动群集。 本月早些时候&#xff0c;Fort…

2022年山东省职业院校技能大赛中职组“网络安全”赛项规程

2022年山东省职业院校技能大赛中职组“网络安全”赛项规程一、赛项名称赛项名称&#xff1a;网络安全英文名称&#xff1a;Cyber Security赛项组别&#xff1a;中职组赛项类别:电子与信息类二、竞赛目的网络空间已经成为陆、海、空、天之后的第五大主权领域空间&#xff0c;习总…

SpringCloud 网关组件 Zuul-1.0 原理深度解析

为什么要使用网关&#xff1f; 在当下流行的微服务架构中&#xff0c;面对多端应用时我们往往会做前后端分离&#xff1a;如前端分成 APP 端、网页端、小程序端等&#xff0c;使用 Vue 等流行的前端框架交给前端团队负责实现&#xff1b;后端拆分成若干微服务&#xff0c;分别…

k8s使用glusterfs(静态供给、动态供给)、glusterfs的安装与使用

目录前言主机准备配置主机名、关闭防火墙、关闭selinux挂载磁盘安装glusterfs服务端glusterfs的端口分布式集群的结构组成glusterfs集群创建存储卷启动卷k8s使用glusterfs作为后端存储&#xff08;静态供给glusterfs存储&#xff09;恢复初始化环境安装Heketi 服务&#xff08;…

如何快速读懂开源代码?

文章目录**RUN起来****调试****把控关键数据结构和函数****从小的开始****关注一个模块****工具****一、阅读开源代码存在的一些误区**二、阅读代码的心态**三、阅读源码与**辅助材料**四、如何阅读开源代码****《gdb 高级调试实战教程》电子书下载链接&#xff1a;**1 下载 Ng…

ASP.NET开源版MES加工装配模拟系统源码/WinForm工厂加工装配系统源码/流程工序管理

一、源码描述 本系统用户大学机械科上位机加工装配模拟实验&#xff0c;目前正常用于实验当中。环境&#xff1a;VS2010(C# .NET4.0,多层结构)、sqlserver2008 r2 &#xff1b;Winform;使用到RFID读写器&#xff08;设备是可以变更的&#xff0c;修改RFID.Library项目的…

Mycat2(一)简介、分库分表概念

文章目录mycat是什么&#xff1b;为什么要用&#xff1b;mycat的作用原理分库分表的意义数据库优化的层次&#xff1a;数据切分的方式&#xff0c;带来的问题和解决方案分库分表带来的问题mycat的特性与详细配置含义mycat2与mycat1.6区别mycat2映射模型多数据源解决方案mycat核…

JavaScript控制元素(标签)的显示与隐藏

使用JavaScript有多种方式来隐藏元素&#xff1a; 方式一、使用HTML 的hidden 属性&#xff0c;隐藏后不占用原来的位置 hidden 属性是一个 Boolean 类型的值&#xff0c;如果想要隐藏元素&#xff0c;就将值设置为 true&#xff0c;否则就将值设置为false 【HTML hidden 属性…