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.rhkb.cn/news/332201.html

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

相关文章

免费图片文字转换成文本,ocr文字识别软件免费版,真的太实用了!

截屏短视频上一段扎心文字&#xff0c;想把它发到朋友圈怎么办&#xff1f;这时候就需要一个OCR识别软件。 它就像一个聪明的小助手&#xff0c;它可以帮助电脑“看懂”书本上或者图片里的字。就像我们用眼睛看字一样&#xff0c;OCR软件用它的“眼睛”扫描图片&#xff0c;识…

【组合数学】常考试题答案

一、单项选择题&#xff08;每小题3分&#xff0c;共15分&#xff09; 1. 用3个“1”和4个“0”能组成&#xff08; &#xff09;个不同的二进制数字。 A. 35 B. 36, C. 37, D. 38 2. 整除300的正整数的个数为&#xff08;  &#xff09;。 A. 14…

Java进阶学习笔记27——StringBuilder、StringBuffer

StringBuilder&#xff1a; StringBuilder代表可变字符串对象&#xff0c;相当于一个容器&#xff0c;它里面装的字符串是可以改变的&#xff0c;就是用来操作字符串的。 好处&#xff1a; StringBuilder比String更适合做字符串的修改操作&#xff0c;效率会更高&#xff0c;…

小白入职 必要熟悉 Git / tortoiseGit 工具

1.安装Git 1.1 了解Git Git是分布式版本控制系统&#xff0c;没有中央服务器的每个人的电脑就是一个完整的版本库&#xff0c;工作时无需联网可多人协作&#xff0c;只需把各自的修改推送给对方&#xff0c;就可以互相看到对方的修改了 分布式版本控制工具管理方式&#xff…

AI崛起,掌握它,开启智能新生活!

AI崛起&#xff0c;掌握它&#xff0c;开启智能新生活&#xff01; &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &…

算法:树状数组

文章目录 面试题 10.10. 数字流的秩327. 区间和的个数315. 计算右侧小于当前元素的个数 树状数组可以理解一种数的存储格式。 面试题 10.10. 数字流的秩 假设你正在读取一串整数。每隔一段时间&#xff0c;你希望能找出数字 x 的秩(小于或等于 x 的值的个数)。 请实现数据结构…

H5扫描二维码相关实现

H5 Web网页实现扫一扫识别解析二维码&#xff0c;就现在方法的npm包就能实现&#xff0c;在这个过程中使用过html5-qrcode 和 vue3-qr-reader。 1、html5-qrcode的使用 感觉html5-qrcode有点小坑&#xff0c;在使用的时候识别不成功还总是进入到错误回调中出现类似NotFoundExc…

mongoengine,一个非常实用的 Python 库!

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个超酷的 Python 库 - mongoengine。 Github地址&#xff1a;https://github.com/MongoEngine/mongoengine 在现代应用程序开发中&#xff0c;NoSQL数据库因其灵活性和高性能而广受欢迎。MongoD…

论文精读--InstructGPT

模型效果取决于数据效果&#xff0c;但在精细度上控制不够&#xff0c;只是大力出奇迹&#xff0c;这样有很大的问题&#xff1a; &#xff08;1&#xff09;数据量太多或者没有这方面的数据&#xff0c;模型学不会怎么办 &#xff08;2&#xff09;安全性问题&#xff0c;模…

制作电子画册速成攻略,快来试试

​当今社会&#xff0c;数字媒体日益普及&#xff0c;电子画册作为一种崭新的展示方式&#xff0c;受到了越来越多人的青睐。它不仅形式新颖&#xff0c;互动性强&#xff0c;而且制作起来也并不复杂。想知道如何快速掌握制作电子画册的技巧吗&#xff1f;我来教你吧。 接下来&…

1-Django开端--学生管理系统

目录 项目结构 前端页面: add_data.html class_data.html index.html apps.py models.py views.py settings,py urls.py ...实现简略的身架... 项目结构 前端页面: add_data.html --添加数据. {% extends index/index.html %}{% block content %} <div class&qu…

关于数据库和数据表的基础SQL

目录 一. 数据库的基础SQL 1. 创建数据库 2. 查看当前有哪些数据库 3. 选中数据库 4. 删除数据库 5. 小结 二. 数据表的基础SQL 1. 创建数据表 2. 查看当前数据库中有哪些表 3. 查看指定表的详细情况(查看表的结构) 4. 删除表 5. 小结 一. 数据库的基础SQL 1. 创建…

设计模式八股文

什么是设计模式&#xff1f; 设计模式是软件开发过程中经常遇到的问题的通用解决方案。类似于前人总结的经验&#xff0c;遇到相似问题的时候有个参考。 设计模式七大基本原则&#xff1f; 单一职责&#xff1a;一个类应该只作一件事情。将功能分为小的独立的单元。开放封闭…

springboot3微服务下结合springsecurity的认证授权实现

1. 简介 在微服务架构中&#xff0c;系统被拆分成许多小型、独立的服务&#xff0c;每个服务负责一个功能模块。这种架构风格带来了一系列的优势&#xff0c;如服务的独立性、弹性、可伸缩性等。然而&#xff0c;它也带来了一些挑战&#xff0c;特别是在安全性方面。这时候就体…

来自Java的“菱形继承“,你听说过吗?

一、菱形继承的概念 菱形继承又叫做钻石继承&#xff0c;指的是不同的类同时继承自相同的父类&#xff0c;存在一个子类同时继承这些不同的类&#xff0c;即我们常说的“多继承”问题。 例如&#xff1a;B类和C类分别继承A类&#xff0c;而D类同时继承B类和C类。 如此图所示 二…

专业渗透测试 Phpsploit-Framework(PSF)框架软件小白入门教程(十三)

本系列课程&#xff0c;将重点讲解Phpsploit-Framework框架软件的基础使用&#xff01; 本文章仅提供学习&#xff0c;切勿将其用于不法手段&#xff01; 接上一篇文章内容&#xff0c;讲述如何进行Phpsploit-Framework软件的基础使用和二次开发。 我们&#xff0c;继续讲一…

Unity | 框架MVC

目录 一、MVC介绍 二、搭建UI界面 三、代码实现 1.Model层 2.View层 3.Controller层 四、MVC框架测试 五、知识补充 一、MVC介绍 model&#xff1a;数据层。界面展示的数据&#xff08;需要进行初始化、更新、保存、事件通知等操作&#xff09;&#xff0c;单例模式&am…

React中显示数据

SX 会让你把标签放到 JavaScript 中。而大括号会让你 “回到” JavaScript 中&#xff0c;这样你就可以从你的代码中嵌入一些变量并展示给用户。例如&#xff0c;这将显示 user.name&#xff1a; return (<h1>{user.name}</h1> ); 你还可以将 JSX 属性 “转义到 …

宁夏银川、山东济南、中国最厉害的改名大师的老师颜廷利教授的前沿思想观点

在当代社会&#xff0c;一个响亮的声音穿越了传统的迷雾&#xff0c;它来自东方哲学的殿堂&#xff0c;由一位现代学者颜廷利教授所发出。他的话语&#xff0c;如同一股清泉&#xff0c;在混沌的世界里激荡着思考的波澜&#xff1a;"有‘智’不在年高&#xff0c;无‘智’…

嵌入式之音频基础知识

声音特性 1、响度&#xff1a;人主观上感觉声音的大小&#xff08;俗称音量&#xff09;&#xff0c;由“振幅”和人离声源的距离决定&#xff0c;振幅越大响度越大&#xff0c;人和声源的距离越小&#xff0c;响度越大&#xff1b; 2、音调&#xff1a;声音的高低&#xff0…