Stream流的使用

目录

一,Stream流

1.1 概述

1.2 Stream代码示例

二,Stream流的使用

2.1 数据准备

2.2 创建流对象

2.3 中间操作

filter

map

distinct

sorted

limit

skip

flatMap

2.4 终结操作

foreach

count

max&min

collect

2.5 查找与匹配

anyMatch

allMatch

noneMatch

findAny

findFirst

2.6 reduce归并

reduce重载方式一:

reduce重载方式二:

2.7 Stream使用注意事项


有关Stream流及函数式编程的相关代码均在我的码云上查看:徐明园/JavaCode - Gitee.com

并内附了详细的Stream流README文档:

一,Stream流

1.1 概述

Java8 Stream使用的是函数式编程( 函数式接口及lambda表达式优化函数式接口-CSDN博客 ),主要是用来对 集合或数组进行链状流式 的操作。可以更方便的让我们对集合或数组操作。

1.2 Stream代码示例

在正式使用Stream流操作集合之前,我们先看一个Stream流的代码示例,对比为使用流操作的代码有什么区别:

未使用Stream流:

//查询未成年作家的评分在70以上的书籍 因为作家和书籍可能出现重复,需要进行去重List<Book> bookList = new ArrayList<>();Set<Book> uniqueBookValues = new HashSet<>();Set<Author> uniqueAuthorValues = new HashSet<>();for(Author author :authors) {if (uniqueAuthorValues.add(author)) {if (author.getAge() < 18) {List<Book> books = author.getBooks();for (Book book : books) {if (book.getScore() > 70) {if (uniqueBookValues.add(book)) {bookList.add(book);}}}}}}System.out.println(bookList);

使用Stream流:

    List<Book> collect = authors.stream().distinct().filter(author -> author.getAge() < 18).map(author -> author.getBooks()).flatMap(Collection::stream).filter(book -> book.getScore() > 70).distinct().collect(Collectors.toList());System.out.println(collect);

不难发现使用Stream流之后的代码看上去会简洁很多,减少了很多for循环以及if/else的判断语句,减少了代码的冗余程度,所以我们需要学习Stream流操作集合的原因有一下几个:

  • 能够看懂公司里的代码(现在大部分公司写业务代码都是使用的Stream流,包括作者在的滴滴,所以可见Stream流的重要性);
  • 大数量下处理集合效率高(这也是Stream流的主要作用);
  • 代码可读性高;
  • 减少代码的嵌套;

二,Stream流的使用

2.1 数据准备

首先我们需要定义两个实体类:分别是Book、Author,并使用CreateAuthors类初始化一些数据:

@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode//用于后期去重
public class Author implements Comparable<Author>{private Long id;private String name;private String introduction;private Integer age;private List<Book> bookList;/*** 使用sorted时比较整个元素时,要实现比较接口,并重写方法*/@Overridepublic int compareTo(Author o) {// return 0; // 这里是如何比较// 0表示年纪一样大,负数表示传入的大// 这里sorted如果输出的是降序,你就把这俩顺序对换就可以了,不用记忆return o.getAge() - this.getAge();}
}@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class Book {private Long id;private String category;private String name;private Integer score;private String introduction;
}public class CreateAuthors {public List<Author> getAuthors() {Author author1 = new Author(1L, "徐明园", "my introduction 1", 19, null);Author author2 = new Author(2L, "xmy", "my introduction 2", 14, null);Author author3 = new Author(2L, "xmy", "my introduction 2", 14, null);Author author4 = new Author(4L, "w", "my introduction 4", 12, null);List<Book> books1 = new ArrayList<>();List<Book> books2 = new ArrayList<>();List<Book> books3 = new ArrayList<>();// 上面是作者和书books1.add(new Book(1L, "类别,分类啊", "书名1", 45, "这是简介哦"));books1.add(new Book(2L, "高效", "书名2", 84, "这是简介哦"));books1.add(new Book(3L, "喜剧", "书名3", 83, "这是简介哦"));books2.add(new Book(5L, "天啊", "书名4", 65, "这是简介哦"));books2.add(new Book(6L, "高效", "书名5", 89, "这是简介哦"));books3.add(new Book(7L, "久啊", "书名6", 45, "这是简介哦"));books3.add(new Book(8L, "高效", "书名7", 44, "这是简介哦"));books3.add(new Book(9L, "喜剧", "书名8", 81, "这是简介哦"));author1.setBookList(books1);author2.setBookList(books2);author3.setBookList(books2);author4.setBookList(books3);return new ArrayList<>(Arrays.asList(author1, author2, author3, author4));}
}

2.2 创建流对象

单列集合:集合对象.stream()

List<Author> authors = getAuthors();
Stream<Author> stream = authors.stream();

数组:Arrays.stream(数组对象)或者使用Stream.of()

Integer[] arr = {1,2,3,4,5};
Stream<Integer> stream = Arrays.stream(arr);
Stream<Integer> stream2 = Stream.of(arr);

双列集合:抓换成单列集合之后再创建

Map<String,Integer> map = new HashMap<>();
map.put("蜡笔小新",19);
map.put("黑子",17);
map.put("日向翔阳",16);
Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();

2.3 中间操作

filter

可以对流中的元素进行条件过滤,符合过滤条件的才能继续留在流中。
//打印所有姓名长度大于1的作家的姓名
List<Author> authors = createAuthors.getAuthors();
authors.stream().filter(author -> author.getName().length()>1).forEach(author -> System.out.println(author.getName()));

map

可以把对流中的元素进行计算或转换。
//将所有作家年龄+10并打印
List<Author> authors = createAuthors.getAuthors();
authors.stream().map(author -> author.getAge()).map(age->age+10).forEach(age-> System.out.println(age));

distinct

可以去除流中的重复元素。
//打印所有作家的姓名,并且要求其中不能有重复元素
List<Author> authors = createAuthors.getAuthors();
authors.stream().distinct().forEach(author -> System.out.println(author.getName()));
注意:distinct方法是依赖Object的equals方法来判断是否是相同对象的。所以需要注意重写equals方法。

sorted

可以对流中的元素进行排序。
//对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素。
//法一:
List<Author> authors = createAuthors.getAuthors();
// 对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素。
authors.stream().distinct().sorted().forEach(author -> System.out.println(author.getAge()));//法二:
List<Author> authors = createAuthors.getAuthors();
// 对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素。
authors.stream().distinct().sorted((o1, o2) -> o2.getAge()-o1.getAge()).forEach(author -> System.out.println(author.getAge()));

要想实现对流中元素进行排序,必须对集合对象自定义排序规则,所以sorted操作提供了两种方法:

  • 不带参数的sorted操作:要求对象自定义排序规则,需要实现Comparable接口并重写方法;
  • 带参数的sorted操作:在使用sorted流时自定义排序规则。

limit

可以设置流的最大长度,超出的部分将被抛弃。
//对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素,然后打印其中年龄最大的两个作家的
姓名。
List<Author> authors = createAuthors.getAuthors();
authors.stream().distinct().sorted().limit(2).forEach(author -> System.out.println(author.getName()));

skip

跳过流中的前 n 个元素,返回剩下的元素。
//打印除了年龄最大的作家外的其他作家,要求不能有重复元素,并且按照年龄降序排序。
List<Author> authors = createAuthors.getAuthors();
authors.stream().distinct().sorted().skip(1).forEach(author -> System.out.println(author.getName()));

flatMap

map 只能把一个对象转换成另一个对象来作为流中的元素。而 flatMap 可以把一个对象转换成多个对象作为流中的元素。
//打印所有书籍的名字。要求对重复的元素进行去重。
List<Author> authors = createAuthors.getAuthors();
authors.stream().flatMap(author -> author.getBooks().stream()).distinct().forEach(book -> System.out.println(book.getName()));

2.4 终结操作

foreach

对流中的元素进行遍历操作,我们通过传入的参数去指定对遍历到的元素进行什么具体操作。
//输出所有作家的名字
List<Author> authors = createAuthors.getAuthors();
authors.stream().map(author -> author.getName()).distinct().forEach(name-> System.out.println(name));

count

可以用来获取当前流中元素的个数。
//打印这些作家的所出书籍的数目,注意删除重复元素。
List<Author> authors = createAuthors.getAuthors();
long count = authors.stream().flatMap(author -> author.getBooks().stream()).distinct().count();
System.out.println(count);

max&min

可以用来或者流中的最值。
//分别获取这些作家的所出书籍的最高分和最低分并打印。
//Stream<Author> -> Stream<Book> ->Stream<Integer> ->求值List<Author> authors = createAuthors.getAuthors();
Optional<Integer> max = authors.stream().flatMap(author -> author.getBooks().stream()).map(book -> book.getScore()).max((score1, score2) -> score1 - score2);
Optional<Integer> min = authors.stream().flatMap(author -> author.getBooks().stream()).map(book -> book.getScore()).min((score1, score2) -> score1 - score2);
System.out.println(max.get());
System.out.println(min.get());

这里先大致看一下Optional对象的使用,下一篇博客详细讲解Optional对象!

collect

把当前流转换成一个集合。
//获取一个存放所有作者名字的List集合。
List<Author> authors = createAuthors.getAuthors();
List<String> nameList = authors.stream().map(author -> author.getName()).collect(Collectors.toList());
System.out.println(nameList);

2.5 查找与匹配

anyMatch

可以用来判断是否有任意符合匹配条件的元素,结果为 boolean 类型。
//判断是否有年龄在29以上的作家
List<Author> authors = createAuthors.getAuthors();
boolean flag = authors.stream().anyMatch(author -> author.getAge() > 29);
System.out.println(flag);

allMatch

可以用来判断是否都符合匹配条件,结果为 boolean 类型。如果都符合结果为 true ,否则结果为 false
//判断是否所有的作家都是成年人
List<Author> authors = createAuthors.getAuthors();
boolean flag = authors.stream().allMatch(author -> author.getAge() >= 18);
System.out.println(flag);

noneMatch

可以判断流中的元素是否都不符合匹配条件。如果都不符合结果为 true ,否则结果为 false。
//判断作家是否都没有超过100岁的。
List<Author> authors = createAuthors.getAuthors();
boolean b = authors.stream().noneMatch(author -> author.getAge() > 100);
System.out.println(b);

findAny

获取流中的任意一个元素。该方法没有办法保证获取的一定是流中的第一个元素。
//获取任意一个年龄大于18的作家,如果存在就输出他的名字
List<Author> authors = createAuthors.getAuthors();
Optional<Author> optionalAuthor = authors.stream().filter(author -> author.getAge()>18).findAny();
optionalAuthor.ifPresent(author -> System.out.println(author.getName()));

findFirst

获取流中的第一个元素。
//获取一个年龄最小的作家,并输出他的姓名。
List<Author> authors = createAuthors.getAuthors();
Optional<Author> first = authors.stream().sorted((o1, o2) -> o1.getAge() - o2.getAge()).findFirst();
first.ifPresent(author -> System.out.println(author.getName()));

2.6 reduce归并

对流中的数据按照你指定的计算方式计算出一个结果。(缩减操作)
reduce 的作用是把 stream 中的元素给组合起来,我们可以传入一个初始值,它会按照我们的计算方式依次拿流中的元素和初始化值进行计算,计算结果再和后面的元素计算。

reduce重载方式一:

T result = identity;
for (T element : this stream)result = accumulator.apply(result, element)
return result;
其中 identity 就是我们可以通过方法参数传入的初始值, accumulator apply 具体进行什么计算也是我们通过方法参数来确定的。
例一:
//使用reduce求所有作者年龄的和
List<Author> authors = createAuthors.getAuthors();
Integer sum = authors.stream().distinct().map(author -> author.getAge()).reduce(0, (result, element) -> result + element);
System.out.println(sum);

例二::

//使用reduce求所有作者中年龄的最大值
List<Author> authors = createAuthors.getAuthors();
Integer max = authors.stream().map(author -> author.getAge()).reduce(Integer.MIN_VALUE, (result, element) -> result < element? element : result);
System.out.println(max);

reduce重载方式二:

boolean foundAny = false;
T result = null;
for (T element : this stream) {if (!foundAny) {foundAny = true;result = element;} elseresult = accumulator.apply(result, element);
}
return foundAny ? Optional.of(result) : Optional.empty();

例一:

//使用reduce求所有作者中年龄的最小值
List<Author> authors = createAuthors.getAuthors();
Optional<Integer> minOptional = authors.stream().map(author -> author.getAge()).reduce((result, element) -> result > element ? element :result);
minOptional.ifPresent(age-> System.out.println(age));

2.7 Stream使用注意事项

  • 惰性求值(如果没有终结操作,没有中间操作是不会得到执行的);
  • 流是一次性的(一旦一个流对象经过一个终结操作后。这个流就不能再被使用);
  • 不会影响原数据(我们在流中可以多数据做很多处理。但是正常情况下是不会影响原来集合中的元素的。这往往也是我们期望的)。

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

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

相关文章

redis中String,Hash类型用法与场景使用

String 用法 1. 设置键值对 &#xff08;1&#xff09;设置键值对使用 set 命令设置 key 的值。 返回值&#xff1a;ok&#xff0c;如果 key 已经存在&#xff0c;set 命令会覆盖旧值。 &#xff08;2&#xff09;使用 setex 命令设置 key 的值并为其设置过期时间&#xff…

安全设计 | CISA:构建不可侵犯的代码,软件安全设计的未来之路

软件制造商在产品设计和开发过程中应采取安全设计原则和方法&#xff0c;以减少网络安全风险&#xff0c;并转变责任重心&#xff0c;使产品在设计时就内置安全特性&#xff0c;而不是依赖于后期的补丁和修复。为此CISA发布了《软件安全设计的原则和方法》&#xff0c;帮助软件…

兵器室管控系统|DW-306是一套成熟系统

概述 智慧兵器室管理系统&#xff08;DW-S306&#xff09;是依托互3D技术、大数据、RFID技术、数据库技术、AI、视频分析技术对RFID智能仓库进行统一管理、分析的信息化、智能化、规范化的系统。 本解决方案利用现有内部网络&#xff0c;部署部队智能兵器室管理系统&#xff…

【Java】欸...?我学集合框架?真的假的?

【Java】欸…&#xff1f;我学集合框架&#xff1f;真的假的&#xff1f; Java集合框架 概述 Java集合框架主要由以下几个部分组成&#xff1a; 接口&#xff08;Interfaces&#xff09;&#xff1a;定义了集合的基本操作&#xff0c;如添加、删除、遍历等。实现&#xff0…

大语言模型的工程技巧(二)——混合精度训练

相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型&#xff1a;从线性回归到通用人工智能》&#xff0c;欢迎有兴趣的读者多多支持。 混合精度训练的示例请参考如下链接&#xff1a;regression2chatgpt/ch11_llm/gpt2_lora_optimum.ipynb 本文将讨论如何利用混合…

Java语法篇-易错

文章目录 类型转换switch case类之间关系及UMLtry catch finally 类型转换 隐式类型转换&#xff0c;不同数值类型参与计算时&#xff0c;低精度会转化为高精度参与运算 byte,short,char参与整数运算时会转成int float,int 参与浮点数运算时会转成double 强制类型转换 高精…

数据结构 —— 栈 与 队列

1.栈 1.1栈的结构和概念 栈&#xff08;Stack&#xff09;是一种特殊的线性数据结构&#xff0c;它遵循后进先出&#xff08;LIFO&#xff0c;Last In First Out&#xff09;的原则。栈只允许在一端插入和删除数据&#xff0c;这一端被称为栈顶&#xff08;top&#xff09;&a…

c++引用和内联函数

一、引用 1.引用概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空 间&#xff0c;它和它引用的变量共用同一块内存空间。&#xff08;引用类型必须和引用实体是同种类型的&#xff09;&#xff0c;如&#x…

MySQL--联合索引应用细节应用规范

目录 一、索引覆盖 1.完全覆盖 2.部分覆盖 3.不覆盖索引-where条件不包含联合索引的最左则不覆盖 二、MySQL8.0在索引中的新特性 1.不可见索引 2.倒序索引 三、索引自优化--索引的索引 四、Change Buffer 五、优化器算法 1.查询优化器算法 2.设置算法 3.索引下推 …

2024年NGFW防火墙安全基准-防火墙安全功效竞争性评估实验室总结报告

Check Point 委托 Miercom 对 Check Point 下一代防火墙 (NGFW) 开展竞争性安全有效性测试&#xff0c; 选择的竞品分别来自 Cisco、Fortinet 和 Palo Alto Networks。对 Zscaler 的测试涉及他们的 SWG&#xff08;安全网关&#xff09;。测试内容包括验证防病毒、反恶意软件、…

SpringBoot+Vue开发记录(六)-- 后端配置mybatis

原型图什么的就先不管&#xff0c;后面再写。 本篇文章的主要内容就是springboot通过mybatis操作数据库实现增删改查。 重点是mybatis配置与相关文件数据&#xff0c;以后开新项目忘记了怎么配置的话可以再照着这个搞。 这算是最基础的部分了吧。 文章目录 一&#xff0c;配置…

基于STM32的自动宠物喂食器的Proteus仿真

文章目录 一、宠物喂食器1.题目要求2.思路2.1 OLED显示汉字2.2 DS1302模块2.3 液位传感器2.4 压力传感器和步进电机驱动 3.仿真图3.1 未仿真时3.2 开始仿真&#xff0c;OLED初始界面显示实时时间3.3 通过设置按键进入模式选择和喂食时间设置3.4 进入喂食时间设置3.5 设置好喂食…

计算机毕业设计Python+Spark+PyTroch游戏推荐系统 游戏可视化 游戏爬虫 神经网络混合CF推荐算法 协同过滤推荐算法 steam 大数据

毕业设计&#xff08;论文&#xff09; 基于SpringBoot的游戏防沉迷系统的设计与实现 摘 要 随着网络游戏市场的持续火爆,其最明显的负面影响----“网络游戏沉迷问题”已成为当前社会普遍关心的热点问题。根据2010年8月1日实施的《网络游戏管理暂行办法》&#xff0c;网络游…

图书管理系统——Java版

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;JavaSE 顺序表的学习&#xff0c;点我 目录 图书管理系统菜单 基本框架&#xff1a; 书&#xff1a; 书架&#xff1a; 用户&#xff…

数字化转型必备:营销策划流程图,打造你的数字市场地图

制作营销策划流程图是一个系统化的过程&#xff0c;它可以帮助你清晰地规划和展示营销活动的各个阶段。 以下是制作营销策划流程图的步骤&#xff1a; 1.确定营销目标&#xff1a; 明确你的营销活动旨在实现的具体目标&#xff0c;比如提升品牌知名度、增加销售额、吸引新客…

Java进阶学习笔记25——Objects类

为啥比较两个对象是否相等&#xff0c;要用Objects的equals方法&#xff0c;而不是用对象自己的equals方法来解决呢&#xff1f; Objects&#xff1a; Objects类是一个工具类&#xff0c;提供了很多操作对象的静态方法供我们使用。 package cn.ensource.d14_objects;import ja…

Hadoop概览以及编译hadoop说明

一、Hadoop概述 Hadoop 是一个用于跨计算机集群存储和处理大型数据集的软件框架。它旨在处理大数据&#xff0c;即传统数据库无法有效管理的极其庞大和复杂的数据集。Hadoop不是传统意义上的数据仓库&#xff0c;因为它们的用途不同&#xff0c;架构也不同。Hadoop 是一个跨分布…

Vue2基础及其进阶面试(二)

vue2的生命周期 删除一些没用的 App.vue 删成这个样子就行 <template><router-view/></template><style lang"scss"></style>来到路由把没用的删除 import Vue from vue import VueRouter from vue-router import HomeView from .…

JAVASE之类和对象(2)

哪怕犯错&#xff0c;也不能什么都不做。 主页&#xff1a;趋早–Step 专栏&#xff1a;JAVASE gitte:https://gitee.com/good-thg 接上部分&#xff0c;我们继续来学习JAVAEE类和对象。 引言&#xff1a; 这篇文章接上一篇&#xff0c;后半部分&#xff0c;结束类和对象 目录 …

Spring Boot 3.0:未来企业应用开发的基石

文章目录 一、Spring Boot 3.0的核心特性二、Spring Boot 3.0的优势三、如何在项目中应用Spring Boot 3.01.更新项目依赖2.调整代码结构3.测试和部署 《学习Spring Boot 3.0》内容简介作者简介目录内容介绍 随着技术的飞速发展&#xff0c;企业应用开发的需求也在不断演变。Spr…