Java8 Stream详细用法介绍

news2024/12/26 23:50:39

Java8 Stream详细用法介绍

  • 一、Stream概述
    • 1.1、流的定义
    • 1.2、流与集合
    • 1.3、流的特性
    • 1.4、Stream的创建
    • 1.5、Stream操作分类
  • 二、Stream API 使用
    • 2.1 中间操作
      • 2.1.1、filter() 过滤
      • 2.1.2、map与flatMap 映射
      • 2.1.3、sorted() 排序
    • 2.2 终止操作
      • 2.2.1、forEach() 遍历
      • 2.2.2、collect() 收集
        • 2.2.2.1、partitioningBy/groupingBy 分区/分组
        • 2.2.2.2、counting 计数
        • 2.2.2.3、averagingDouble 平均值
        • 2.2.2.4、maxBy minBy 最值
        • 2.2.2.5、summarizingDouble 统计
      • 2.2.3、match() 匹配
      • 2.2.4、count() max() sum() 聚合
      • 2.2.5、reduce() 规约

一、Stream概述

Stream流是JDK8新增的成员,允许以声明性方式处理数据集合,可以把Stream流看作是遍历数据集合的一个高级迭代器。Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找/筛选/过滤、排序、聚合和映射数据等操作。Stream API 提供了一种高效且易于使用的处理数据的方式。

1.1、流的定义

从支持数据处理操作的源生成的元素序列。数据源可以是集合,数组或IO资源。

1.2、流与集合

streamCollection
主要用途主要用于描述对数据的计算主要为了存储和访问数据
计算时间在有需求的时候才计算每个元素都是先计算出来的
遍历方式内部迭代外部迭代

1.3、流的特性

  • 不是数据结构,不会保存数据,stream的目的是处理数据。
  • stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
  • 惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算。

1.4、Stream的创建

1、通过Stream.empty()创建空流

Stream<String> streamEmpty = Stream.empty();

2、通过 java.util.Collection.stream() 方法用集合创建流

List<String> list = Arrays.asList("a", "b", "c");
// 创建一个顺序流
Stream<String> stream = list.stream();
// 创建一个并行流
Stream<String> parallelStream = list.parallelStream();

3、使用 java.util.Arrays.stream(T[]array)方法用数组创建流

int[] array={1,3,5,6,8};
IntStream stream = Arrays.stream(array);

4、通过构造器 Stream.builder() 创建

使用构建器时,应在语句的右侧部分另外指定所需类型,否则build()方法将创建Stream 的实例

Stream<String> streamBuilder = 
	Stream.<String>builder().add("a").add("b").add("c").build();

5、使用 Stream的静态方法:of()、iterate()、generate()

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
Stream<Double> stream3 = Stream.generate(Math::random).limit(3);

6、通过 File 创建

Java NIO类Files允许通过lines()方法生成文本文件的Stream 。 文本的每一行都成为流的一个元素:

Path path = Paths.get("C:\\file.txt");
Stream<String> streamOfFile = Files.lines(path);
Stream<String> streamWithCharset = Files.lines(path, Charset.forName("UTF-8"));

1.5、Stream操作分类

在这里插入图片描述

Stream操作分为两种:

  • 中间操作,每次返回一个新的流,可以有多个。

    • 无状态:指元素的处理不受之前元素的影响;
    • 有状态:指该操作只有拿到所有元素之后才能继续下去。
  • 终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。

    • 非短路操作:指必须处理所有元素才能得到最终结果;
    • 短路操作:指遇到某些符合条件的元素就可以得到最终结果,如 A || B,只要A为true,则无需判断B的结果。

在这里插入图片描述

二、Stream API 使用

2.1 中间操作

2.1.1、filter() 过滤

过滤器根据给定的谓词过滤流的所有元素,并返回一个新的流。
在这里插入图片描述
数据准备:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Fruit {
    //id
    private Integer id;
    //名称
    private String name;
    //颜色
    private String color;
    //数量
    private Integer num;
    //重量
    private Double weight;
}

List<Fruit> fruitList = new ArrayList<>();
fruitList.add(new Fruit(1, "apple", "green", 4, 300.0));
fruitList.add(new Fruit(2, "apple", "red", 14, 325.0));
fruitList.add(new Fruit(3, "apple", "yellow", 27, 450.0));
fruitList.add(new Fruit(4, "orange", "yellow", 10, 100.0));
fruitList.add(new Fruit(5, "banana", "yellow", 22, 250.0));
//1.查找重量大于400的苹果 filter
fruitList.stream().filter(p -> p.getName().equals("apple"))
	.filter(p -> p.getWeight() > 400.0)
	.forEach(System.out::println);
//结果输出
Fruit(id=3, name=apple, color=yellow, num=27, weight=450.0)

2.1.2、map与flatMap 映射

map:对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素,一对一映射
在这里插入图片描述

//2.将每种颜色苹果的数量增加5 map
fruitList.stream().filter(p -> p.getName().equals("apple"))
	.map(m -> m.getNum() + 5)
	.forEach(System.out::println);
//输出结果,新生成的Stream只包含苹果的数量
9
19
32

flatMap:对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素,一对多映射
在这里插入图片描述

//3.输出各种颜色苹果的数量 flatMap
fruitList.stream().filter(p -> p.getName().equals("apple"))
	.flatMap(m -> Stream.of(m.getColor() + ": " + m.getNum()))
	.forEach(System.out::println);
//输出结果
green: 4
red: 14
yellow: 27

2.1.3、sorted() 排序

对 Stream 的排序通过 sorted 进行,它比数组的排序更强之处在于你可以首先对 Stream 进行各类 map、filter、limit、skip 甚至 distinct 来减少元素数量后,再排序,这能帮助程序明显缩短执行时间。

//4.按重量由大到小对苹果进行排序 sorted倒序排
fruitList.stream().filter(p -> p.getName().equals("apple"))
	.sorted(Comparator.comparing(Fruit::getWeight).reversed())
	.forEach(System.out::println);
//输出结果
Fruit(id=3, name=apple, color=yellow, num=27, weight=450.0)
Fruit(id=2, name=apple, color=red, num=14, weight=325.0)
Fruit(id=1, name=apple, color=green, num=4, weight=300.0)

2.2 终止操作

2.2.1、forEach() 遍历

//5.forEach遍历
fruitList.stream().forEach(System.out::println);

2.2.2、collect() 收集

collect()方法用于从steam 收集元素并将它们存储在集合中。

//6.筛选出颜色为黄色的水果 collect收集
fruitList.stream().filter(f -> f.getColor().equals("yellow"))
	.collect(Collectors.toList())
	.forEach(System.out::println);
//输出结果
Fruit(id=3, name=apple, color=yellow, num=27, weight=450.0)
Fruit(id=4, name=orange, color=yellow, num=10, weight=100.0)
Fruit(id=5, name=banana, color=yellow, num=22, weight=250.0)

2.2.2.1、partitioningBy/groupingBy 分区/分组

partitioningBy 分区:将stream按条件分为两个 Map,比如重量是否高于300g分为两部分。

groupingBy 分组:将集合分为多个Map,比如水果按类型分组。有单级分组和多级分组。

在这里插入图片描述

//8.分组
//按重量是否高于300g分组 partitioningBy分区
Map<Boolean, List<Fruit>> collect = fruitList.stream().collect(Collectors.partitioningBy(p -> p.getWeight() > 300.0));
System.out.println("按重量是否高于300g分组:" + collect);
//按水果类型分组
Map<String, List<Fruit>> collect1 = fruitList.stream().collect(Collectors.groupingBy(Fruit::getName));
System.out.println("按水果类型分组:" + collect1);
//按水果类型、颜色分组
Map<String, Map<String, List<Fruit>>> collect2 =
        fruitList.stream().collect(Collectors.groupingBy(Fruit::getName, Collectors.groupingBy(Fruit::getColor)));
System.out.println("按水果类型、颜色分组:" + collect2);

2.2.2.2、counting 计数

可使用count()聚合函数代替

2.2.2.3、averagingDouble 平均值

Double avgWeight = fruitList.stream().collect(Collectors.averagingDouble(Fruit::getWeight));
System.out.println("平均重量 = " + avgWeight);  //平均重量 = 285.0

2.2.2.4、maxBy minBy 最值

可使用 max()、min()聚合函数代替

2.2.2.5、summarizingDouble 统计

DoubleSummaryStatistics statistics = fruitList.stream().collect(Collectors.summarizingDouble(Fruit::getWeight));
//重量统计 = DoubleSummaryStatistics{count=5, sum=1425.000000, min=100.000000, average=285.000000, max=450.000000}
System.out.println("重量统计 = " + statistics);

2.2.3、match() 匹配

Stream 有三个 match 方法:

  • allMatch:Stream 中全部元素符合传入的 predicate,返回 true
  • anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true
  • noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true
//7.匹配match
//anyMatch 任意一个匹配
fruitList.stream().anyMatch(p->p.getColor().contains("green")); //true
//noneMatch 全部不匹配
fruitList.stream().noneMatch(p->p.getColor().contains("green")); //false
//allMatch 全部匹配
fruitList.stream().allMatch(p->p.getColor().contains("green")); //false

2.2.4、count() max() sum() 聚合

// 8.聚合
//计算水果总数 sum
int sum = fruitList.stream().mapToInt(Fruit::getNum).sum();
System.out.println("sum = " + sum); //sum = 77
//计算水果种类数量 count
long count = fruitList.stream().map(Fruit::getName).distinct().count();
System.out.println("水果种类数量 = " + count);    //水果种类数量 = 3
//计算不同类型的水果数量 先分组再求和
Map<String, Integer> tSum = fruitList.stream().collect(Collectors.groupingBy(Fruit::getName, Collectors.summingInt(Fruit::getNum)));
System.out.println("tSum = " + tSum);   //tSum = {banana=22, orange=10, apple=45}
//最大重量 max
Optional<Fruit> max = fruitList.stream().max(Comparator.comparing(Fruit::getWeight));
System.out.println("最大重量 = " + max);    //最大重量 = Optional[Fruit(id=3, name=apple, color=yellow, num=27, weight=450.0)]

2.2.5、reduce() 规约

归约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。
在这里插入图片描述

List<Integer> list = Arrays.asList(1, 2, 3, 4);
//求和
Optional<Integer> reduce = list.stream().reduce((x, y) -> x + y);
System.out.println("求和:" + reduce.get()); //10
//求积
Optional<Integer> reduce2 = list.stream().reduce((x, y) -> x * y);
System.out.println("求积:" + reduce2.get());	//24
//求最大值
Optional<Integer> reduce3 = list.stream().reduce((x, y) -> x > y ? x : y);
System.out.println("求最大值:" + reduce3.get());	//4

//计算水果总数
Optional<Integer> sum = fruitList.stream().map(Fruit::getNum).reduce(Integer::sum);
System.out.println("sum = " + sum.get()); //sum = 77
//计算最大重量
Optional<Double> maxWeight = fruitList.stream().map(Fruit::getWeight).reduce(Double::max);
System.out.println("maxWeight = " + maxWeight.get());   //maxWeight = 450.0

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

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

相关文章

ThinkPHP 多应用模式下访问其他应用忽略入口文件

目录 问题描述&#xff1a; 解决方法&#xff1a; 1.配置两个域名分别指向项目public目录 2.项目全局配置域名绑定应用 问题描述&#xff1a; 使用TP6.0做多应用项目开发&#xff0c;分为前端Api和后台管理 项目中已配置地址重写规则 Api为默认应用&#xff0c;可忽略入…

Allegro如何手动和自动10度走线操作指导

Allegro如何手动和自动10度走线操作指导 PCB上有时需要10度走线,可以有效的避免玻纤效应的产生,尤其是在应对高速设计的时候,Allegro支持10度走线如下图 具体操作如下 选择setup Parameter选择route

50个超级有用的JavaScript单行代码

在这篇文章中&#xff0c;我列出了一个系列的50个 JavaScript 单行代码&#xff0c;它们在使用 vanilla js&#xff08;≥ ES6&#xff09;进行开发时非常有用。它们也是使用该语言在最新版本中为我们提供的所有功能来解决问题的优雅方式。 我将它们分为以下5大类&#xff1a;…

波士顿房价数据集进行数据预处理和模型训练(Python)

目录 前言 一、数据预处理定义 二、波士顿房价数据进行数据预处理 2.1 下载波士顿房价数据集 2.2 查看数据集的描述、特征及数据条数、特征数量 2.3 将数据读入pandas的DataFrame并转存到csv文件 2.4 查看数据集各个特征的类型以及是否有空值 2.5 对数据集做中心化度量&a…

自动驾驶技术平台分享:百度Apollo开放平台8.0再升级,更简单,更便捷,更高效

文章目录自动驾驶技术入门&#xff0c;先看平台Appllo主要优势版本更新新特性颠覆更新“新”架构全新加入软件包管理机制加入新感知模型感知全流程开放与提效全新PnC工具链写在最后自动驾驶技术入门&#xff0c;先看平台 近年来&#xff0c;自动化驾驶的话题越来越成为热点。对…

【十天成为红帽工程师】第六天 DNS域名解析服务器

目录 一、域名解析服务器的介绍 二、DNS域名解析的过程 三、搭建DNS服务器 一、域名解析服务器的介绍 DNS&#xff08;Domain Name System&#xff09;是互联网上的一项服务&#xff0c;它作为将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便的访问互…

ChatGPT:新晋CV工程师

在短短的两个星期内&#xff0c;ChatGPT 迅速成为公众聊天的焦点。超过一百万的人与OpenAI的新聊天机器人“交谈”&#xff0c;让它写诗和大学论文&#xff0c;生成创意食谱&#xff0c;创建虚拟机…它也被用来撰写新闻文章和YouTube视频的介绍。作为计算机视觉公司的机器学习工…

Qt第五十一章:Qt样式表-Qss

目录 一、盒子模型 二、选择器 三、伪状态 四、字体 五、边框 六、背景 七、边距 八、示例大全 一、盒子模型 二、选择器 选择器示例描述通用选择器*匹配所有控件类型选择器QPushButton匹配给定类型控件&#xff0c;包括子类类选择器.QPushButton匹配给定类型控件&…

【PAT甲级 - C++题解】1032 Sharing

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;PAT题解集合 &#x1f4dd;原题地址&#xff1a;题目详情 - 1032 Sharing (pintia.cn) &#x1f511;中文翻译&#xff1a;共享 &#x1f4e3;专栏定位&…

[ 代码审计篇 ] 代码审计案例详解(二) XXE代码审计案例

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

年底了,手机通讯录和相册被恶意APP获取,看我如何破局?

☆ 最近几天突然收到一个朋友的深夜短信&#xff0c;被告知如果有人发送不明信息&#xff0c;或者发送任何不明链接&#xff0c;都不要点开。我经过问朋友&#xff0c;得知下载了一个恶意的APP&#xff0c;把通讯录和手机相册获取了。 ☆ 年底了&#xff0c;很多人发愁过年没有…

ASIO IO_CONTEXT 源码整理

io_context关系图 io_context io_context::io_context(): impl_(add_impl(new impl_type(*this,ASIO_CONCURRENCY_HINT_DEFAULT, false))) { }io_context::io_context(int concurrency_hint): impl_(add_impl(new impl_type(*this, concurrency_hint 1 ? ASIO_CONCURRENCY_HI…

一千元以内的蓝牙耳机推荐,2023年最值得入手的蓝牙耳机分享

对于蓝牙耳机的选购技巧&#xff0c;我还是比较了解的&#xff0c;也知道有哪些蓝牙耳机比较好用&#xff0c;音质也好&#xff0c;但还是有很多人不知道该如何选购耳机&#xff0c;我也总是被问到蓝牙耳机挑选的相关问题&#xff0c;今天就来跟大家一起来了解了解什么蓝牙耳机…

看我这篇没人比你更懂RecyclerView的预加载

实际上&#xff0c;预拉取(prefetch)机制作为RecyclerView的重要特性之一&#xff0c;常常与缓存复用机制一起配合使用、共同协作&#xff0c;极大地提升了RecyclerView整体滑动的流畅度。 并且&#xff0c;这种特性在ViewPager2中同样得以保留&#xff0c;对ViewPager2滑动效…

【面试题】请你谈谈MySQL性能调优的方法

【面试题】请你谈谈MySQL性能调优的方法 这个问题是一个开放性问题&#xff0c;本人这一段时间参加面试&#xff08;2022.12.26&#xff09;经常被问道...... 刚刚开始我回答的很混乱&#xff01;虽然真的知道MySQL性能调优的方法&#xff0c;也做过类似的工作&#xff0c;但…

【BF算法】

BF 算法 BF 算法精讲 在学习到字符串的匹配问题时&#xff0c;了解到了BF算法和KMP算法。 对比这两个算法&#xff0c;先了解BF算法&#xff1b; 字符串匹配问题&#xff0c;比如说&#xff1a;有一个主串 “abbbcdef” &#xff0c; 子串 “bbc”&#xff0c;该问题就是在主…

Linux基础 - DNS服务基础

‍‍&#x1f3e1;博客主页&#xff1a; Passerby_Wang的博客_CSDN博客-系统运维,云计算,Linux基础领域博主 &#x1f310;所属专栏&#xff1a;『Linux基础』 &#x1f30c;上期文章&#xff1a; Linux基础 - Web服务基础 &#x1f4f0;如觉得博主文章写的不错或对你有所帮助…

共享内存和消息队列

共享内存 共享内存指 (shared memory)在多处理器的计算机系统中&#xff0c;可以被不同中央处理器(CPU)访问的大容量内存。由于多个CPU需要快速访问存储器&#xff0c;这样就要对存储器进行缓存(Cache)。任何一个缓存的数据被更新后&#xff0c;由于其他处理器也可能要存取&am…

某程序员哀叹:有比我更惨的吗?工作6年攒了200万,高位接盘买了600万的房子,现在房子跌了100多万,每个月还要还2万房贷!...

最近这几年&#xff0c;“人间惨事”层出不穷&#xff0c;许多网友都在网上比惨&#xff0c;今天的故事主角是一位程序员。这位程序员哀叹&#xff1a;有比我更惨的吗&#xff1f;工作6年攒了200多万&#xff0c;凑了300万首付&#xff0c;在杭州未来科技城高位接盘买了600万的…

JavaScript普通函数与箭头函数有怎样的区别?

比较点 普通函数 箭头函数 具体案例 简写 / 箭头函数如果没有参数&#xff0c;同时函数体的返回值只有一句&#xff0c;则{}和return都可以省略。 1、函数简写 this指向 this总是指向调用它的对象&#xff0c;如果作为构造函数&#xff0c;它指向创建的对象实例 箭头…