Java基础:Stream流常用方法
获取Stream流的方式
java.util.stream.Stream 是Java 8新加入的流接口。(并不是一个函数式接口)
获取一个流非常简单,有以下几种常用的方式:
- 所有 Collection 集合都可通过 stream 默认方法获取流(顺序流)
- 所有 Collection 集合都可通过parallelStream获取并行流
- Stream 接口的静态方法 of 可以获取数组对应的流。
- Arrays的静态方法stream也可以获取流
根据Collection获取流
public static void main(String[] args) {List<String> list = new ArrayList<>();Stream<String> stream1 = list.stream();Set<String> set = new HashSet<>();Stream<String> stream2 = set.stream();Vector<String> vector = new Vector<>();// ...
}
根据Map获取流
public static void main(String[] args) {Map<String, String> map = new HashMap<>();Stream<String> keyStream = map.keySet().stream();Stream<String> valueStream = map.values().stream();Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
}
根据数组获取流
如果使用的不是集合或映射而是数组,由于数组对象不可能添加默认方法,所以 Stream 接口中提供了静态方法of ,使用很简单:
public static void main(String[] args) {//使用 Stream.ofString[] array = { "张无忌", "张翠山", "张三丰", "张一元" };Stream<String> stream = Stream.of(array);//使用Arrays的静态方法Arrays.stream(array)
}
Stream流中的常用方法
方法可分成两种:
- 延迟方法:返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。(除终结方法外,其余方法均为延迟方法)
- 终结方法:返回值类型不是 Stream 接口自身类型的方法,因此不再支持类似 StringBuilder 那样的链式调用。本节中,终结方法包括 count 和 forEach 方法。
1.forEach(终结方法)
用于遍历的方法,参数传入一个函数式接口:Consumer
public static void main(String[] args) {Stream<String> stream = Stream.of("张无忌", "张三丰", "周芷若");stream.forEach(name‐> System.out.println(name));
}
2.过滤:filter
可用于过滤。可通过 filter 方法将一个流转换成另一个子集流。
public static void main(String[] args) {//创建一个流Stream<String> stream = Stream.of( "刘德华", "张国荣", "彭于晏", "纳什", "吴彦祖");//对流中元素过滤,只要姓张的人Stream<String> stream2 = stream.filter(name -> {return name.startsWith("张");});//遍历过滤后的流stream2.forEach(name -> System.out.println(name));
}
3.映射(转换):map
如果需要将流中的元素映射到另一个流中,可用 map 方法。
该接口需要一个 Function 函数式接口参数
/*** stream流的map方法练习* map方法可以将流中的元素映射到另一个流中* map方法的参数是一个Function函数式接口*/@Testpublic void test(){//创建一个流,里面是字符串类型的整数Stream<String> stream1 = Stream.of("2", "32", "2", "33", "2");//把stream1流中的整数全部转成int类型Stream<Integer> stream2 = stream1.map((String s) -> {return Integer.parseInt(s);});//遍历stream2.forEach((i)-> System.out.println(i));}
4.统计个数:count(终结方法)
正如旧集合 Collection 当中的 size 方法一样,流提供 count 方法来数一数其中的元素个数:
该方法返回一个long值代表元素个数(不像旧集合那样是int值)。
public class Demo09StreamCount {public static void main(String[] args) {Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");//筛选姓张的Stream<String> result = original.filter(s ‐> s.startsWith("张"));//输出个数System.out.println(result.count()); // 2}
}
5.取用前几个(截取):limit
limit 方法可对流进行截取,只取用前n个。
参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作。
public class Demo10StreamLimit {public static void main(String[] args) {Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");//截取前两个Stream<String> result = original.limit(2);System.out.println(result.count()); // 2}
}
6.跳过前几个元素:skip
如果希望跳过前几个元素,可用 skip 方法获取一个截取后的新流:
如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。
public class Demo11StreamSkip {public static void main(String[] args) {Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");//跳过前两个,返回一个新的流Stream<String> result = original.skip(2);System.out.println(result.count()); // 1}
}
7.组合(合并流):concat
如果有两个流,希望合并为一个流,可以用 Stream 接口的静态方法 concat :
public class Demo12StreamConcat {public static void main(String[] args) {Stream<String> streamA = Stream.of("张无忌");Stream<String> streamB = Stream.of("张翠山");//合并成一个新的流Stream<String> result = Stream.concat(streamA, streamB);}
}
8.筛选:distinct
去除流中重复元素(使用hashcode和equals方法来对比)
9.映射(打开后再转换):flatMap
内部传入一个Function函数式接口,跟map的区别就是这个会把流中的元素打开,再组合成一个新的流
// map和flatMap的练习
public class StreamDemo {@Testpublic void test(){List<String> list = Arrays.asList("aa","bb","cc","dd");// 练习1 (map) 输出的全是大写list.stream().map(s -> s.toUpperCase()).forEach(System.out::println);System.out.println("----------");// 练习2(map)流里还有流,需要两个遍历才行看到里面内容Stream<Stream<Character>> streamStream = list.stream().map(StreamDemo::fromStringToStream);streamStream.forEach(s -> {s.forEach(System.out::println);});System.out.println("---------");// 练习3(flatMap)流里还有流,使用flatMap可以直接把里面的流打开,一次遍历就可以了Stream<Character> characterStream = list.stream().flatMap(StreamDemo::fromStringToStream);characterStream.forEach(System.out::println);}/*** 将字符串中的多个字符构成的集合转换为对应的stream* @param str* @return*/public static Stream<Character> fromStringToStream(String str){ArrayList<Character> list = new ArrayList();// 将字符串转成字符数组,并遍历加入list集合for(Character c : str.toCharArray()){list.add(c);}// 返回list集合的stream流return list.stream();}
}
10.自然排序:sorted
看下一条里的代码
11.定制排序:sorted(Comparator com)
/*** 排序的练习*/@Testpublic void test2(){List<Integer> integers = List.of(124, 2, 15, 12, 51, -5, 5);// 按照自然排序integers.stream().sorted().forEach(System.out::println);System.out.println("---------");List<Integer> integers2 = List.of(124, 2, 15, 12, 51, -5, 5);// 定制排序(大到小),需要传入Comparator接口(如果流中的是引用类型,只能用定制排序)// 简写:integers2.stream().sorted((e1,e2) -> e2-e1).forEach(System.out::println);integers2.stream().sorted((e1,e2) -> {return e2-e1;}).forEach(System.out::println);}
12.检测匹配(终结方法):
返回一个Boolean值
是否全部匹配:allMatch
是否至少匹配一个:anyMatch
是否没有匹配的:noneMatch
/*** 匹配的练习*/@Testpublic void test3(){List<Integer> integers = List.of(124, 2, 15, 12, 51, -5, 5);// 判断是否全部大于5boolean b = integers.stream().allMatch(i -> i > 5);// 结束输出falseSystem.out.println(b);System.out.println("-------");List<Integer> integers2 = List.of(124, 2, 15, 12, 51, -5, 5);// 检测是否匹配至少一个元素boolean b1 = integers2.stream().anyMatch(i -> i > 5);// 输出trueSystem.out.println(b1);System.out.println("-------");List<Integer> integers3 = List.of(124, 2, 15, 12, 51, -5, 5);// 检查是否没有匹配的元素boolean b2 = integers3.stream().noneMatch(i -> i > 1000);// 输出true,全部不匹配System.out.println(b2);}
13.查找元素(终结方法)
查找第一个元素:findFirst,返回Optional类型
查找其中一个元素:findAny,返回Optional类型
public void test4(){List<Integer> integers = List.of(124, 2, 15, 12, 51, -5, 5);// 输出第一个元素Optional<Integer> first = integers.stream().findFirst();// 输出结果是Optional[124]System.out.println(first);System.out.println("-------------");List<Integer> integers2 = List.of(124, 2, 15, 12, 51, -5, 5);// 返回其中一个元素Optional<Integer> any = integers2.stream().findAny();System.out.println(any);}
14.查找最大最小值(终结方法)
max(comparator c)
min(comparator c)
/*** 查找最大最小值*/@Testpublic void test5(){List<Person> list = new ArrayList<>();list.add(new Person("马化腾",25,3000));list.add(new Person("李彦宏",27,2545));list.add(new Person("雷军",35,4515));list.add(new Person("马云",55,9877));// 查找年龄最大的人Optional<Person> max = list.stream().max((e1, e2) -> e1.getAge() - e2.getAge());// 返回马云,55岁年龄最大System.out.println(max.get());System.out.println("--------");
15.规约(终结方法)
reduce(T identity ,BinaryOperator) 第一个参数是初始值,第二个参数是一个函数式接口
reduce(BinaryOperator) 参数是一个函数式接口
/*** 归约的练习*/@Testpublic void test6(){List<Integer> integers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 求集合里数字的和(归约)reduce第一个参数是初始值。Integer sum = integers.stream().reduce(0, Integer::sum);System.out.println(sum);System.out.println("-------");List<Person> list = new ArrayList<>();list.add(new Person("马化腾",25,3000));list.add(new Person("李彦宏",27,2545));list.add(new Person("雷军",35,4515));list.add(new Person("马云",55,9877));// 求所有人的工资和(归约)// 不用方法引用写法:Optional<Integer> reduce = list.stream().map(person -> person.getSalary()).reduce((e1, e2) -> e1 + e2);Optional<Integer> reduce = list.stream().map(Person::getSalary).reduce(Integer::sum);// 输出Optional[19937]System.out.println(reduce);}
16.收集(终结方法)
collect(Collector c):将流转化为其他形式,接收一个Collector接口的实现
/*** 收集的练习*/@Testpublic void test7(){List<Person> list = new ArrayList<>();list.add(new Person("马化腾",25,3000));list.add(new Person("李彦宏",27,2545));list.add(new Person("雷军",35,4515));list.add(new Person("马云",55,9877));// 把年龄大于30岁的人,转成一个list集合List<Person> collect = list.stream().filter(person -> person.getAge() > 30).collect(Collectors.toList());// 遍历输出(输出雷军和马云)for (Person person : collect) {System.out.println(person);}System.out.println("----------");List<Person> list2 = new ArrayList<>();list2.add(new Person("马化腾",25,3000));list2.add(new Person("李彦宏",27,2545));list2.add(new Person("雷军",35,4515));list2.add(new Person("马云",55,9877));// 把姓马的人,转成Set集合Set<Person> set = list2.stream().filter(person -> person.getName().startsWith("马")).collect(Collectors.toSet());// 输出马云和马化腾set.forEach(System.out::println);}
17.迭代:iterate
可以使用Stream.iterate创建流值,即所谓的无限流。
//Stream.iterate(initial value, next value)Stream.iterate(0, n -> n + 1).limit(5).forEach(x -> System.out.println(x));
输出:
0
1
2
3
4
18.查看:peek
peek接收的是一个Consumer函数,peek 操作会按照 Consumer 函数提供的逻辑去消费流中的每一个元素,同时有可能改变元素内部的一些属性
@Testpublic void test1(){List<String> collect = Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3).peek(e -> System.out.println("查看一下刚过滤出的值:" + e)).map(String::toUpperCase).peek(e -> System.out.println("查看一下转大写之后的值:" + e)).collect(Collectors.toList());System.out.println("-----分割线-----");// 遍历过滤后的集合for (String s : collect) {System.out.println(s);}}
输出:
查看一下刚过滤出的值:three
查看一下转大写之后的值:THREE
查看一下刚过滤出的值:four
查看一下转大写之后的值:FOUR
-----分割线-----
THREE
FOUR
Srtream流中方法的使用练习
/*** 1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。* 2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。* 3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。* 4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。* 5. 将两个队伍合并为一个队伍;存储到一个新集合中。* 6. 根据姓名创建 Person 对象;存储到一个新集合中。* 7. 打印整个队伍的Person对象信息。*/
public class Demo3 {public static void main(String[] args) {//第一支队伍ArrayList<String> one = new ArrayList<>();one.add("迪丽热巴");one.add("宋远桥");one.add("苏星河");one.add("石破天");one.add("石中玉");one.add("老子");one.add("庄子");one.add("洪七公");//第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。//第一个队伍筛选之后只要前3个人;存储到一个新集合中。Stream<String> stream = one.stream();Stream<String> stream1 = stream.filter(name -> name.length() == 3).limit(3);//第二支队伍ArrayList<String> two = new ArrayList<>();two.add("古力娜扎");two.add("张无忌");two.add("赵丽颖");two.add("张三丰");two.add("尼古拉斯赵四");two.add("张天爱");two.add("张二狗");//第二个队伍只要姓张的成员姓名;存储到一个新集合中。//第二个队伍筛选之后不要前2个人;存储到一个新集合中。Stream<String> stream2 = two.stream();Stream<String> stream3 = stream2.filter(name -> name.startsWith("张")).skip(2);//合并两个队伍Stream<String> concat = Stream.concat(stream1, stream3);//把合并后的队伍根据姓名创建Person对象,并存入新的集合中,然后打印concat.map(name -> new Person(name)).forEach(p -> System.out.println(p));}
}
相关文章:
Java基础:Stream流常用方法
获取Stream流的方式 java.util.stream.Stream 是Java 8新加入的流接口。(并不是一个函数式接口) 获取一个流非常简单,有以下几种常用的方式: 所有 Collection 集合都可通过 stream 默认方法获取流(顺序流)…...

ImageNet使用方法(细节)自用!
学习记录,自用。 1. 下载数据集 点击以下链接下载种子文件,然后使用迅雷进行下载,仅下载勾选的文件即可。 https://hyper.ai/datasets/4889/c107755f6de25ba43c190f37dd0168dbd1c0877e 2. 解压 找到下载好的ILSVRC2012_img_train.tar 和…...
C/C++外观模式解析:简化复杂子系统的高效方法
C外观模式揭秘:简化复杂子系统的高效方法 引言设计模式的重要性外观模式简介与应用场景外观模式在现代软件设计中的地位与价值 外观模式基本概念外观模式的定义与核心思想提供简单接口隐藏复杂子系统设计原则与外观模式的关系外观模式实现外观模式的UML图 外观模式的…...

追梦之旅【数据结构篇】——详解小白如何使用C语言实现堆数据结构
详解小白如何使用C语言实现堆数据结构 “痛”撕堆排序~😎 前言🙌什么是堆?堆的概念及结构 堆的性质:堆的实现堆向下调整算法画图分析:堆向下调整算法源代码分享:向下调整建小堆向下调整建大堆 堆向上调整算…...

cocoscreator性能优化4-Sprite颜色数据去除
前言 Sprite是游戏内容的一个基本组成元素,包括ui、道具、立绘等各种地方都会用到。大部分情况下美术会帮我们调好图片颜色,我们只要把图片直接放到游戏里就行了。Sprite默认的渲染顶点数据中包含了颜色数据,由于我们并不需要去修改颜色&…...
系统接口幂等性设计探究
前言: 刚开始工作的时候写了一个带UI页面的工具,需要设计登录功能,登录功能也很简单,输入用户名密码点击登录,触发后台查询并比对密码,如果登录成功则返回消息给前端,前端把消息弹出提示一下。…...

C learning_7
目录 1.for循环 1.虽然while循环和for循环本质上都可以实现循环,但是它们在使用方法和场合上还是有一些区别的。 2.while循环中存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样 查找修改就不够集中和方便。所以…...
PageRank算法介绍
互联网上有数百亿个网页,可以分为这么几类:不含有用信息的,比如垃圾邮件;少数人比较感兴趣的,但范围不是很广的,比如个人博客、婚礼公告或家庭像册;很多人感兴趣的并且十分有用的,比…...

springboot+vue职称评审管理系统(源码+文档)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的职称评审管理系统。项目源码请联系风歌,文末附上联系信息 。 目前有各类成品java毕设,需要请看文末联系方式 …...

腾讯云4核8G轻量服务器12M支持多少访客同时在线?并发数怎么算?
腾讯云轻量4核8G12M轻量应用服务器支持多少人同时在线?通用型-4核8G-180G-2000G,2000GB月流量,系统盘为180GB SSD盘,12M公网带宽,下载速度峰值为1536KB/s,即1.5M/秒,假设网站内页平均大小为60KB…...

图片英文翻译成中文转换器-中文翻译英文软件
您正在准备一份重要的英文资料或文件,但是您还不是很熟练地掌握英文,需要翻译才能完成您的任务吗?哪个软件能够免费把英文文档翻译成中文?让我们带您了解如何使用我们的翻译软件来免费翻译英文文档为中文。 我们的翻译软件是一款功…...

月薪10k和40k的程序员差距有多大?
程序员的薪资一直是大家关注的焦点,相较于其他行业,程序员的高薪也是有目共睹的,而不同等级的程序员处理问题的方式与他们的薪资直接挂钩。 接下来就一起看一下月薪10k、20k、30k、40k的程序员面对问题都是怎么处理的吧! 场景一 …...

gateway整合knife4j(微服务在线文档)
文章目录 knife4j 微服务整合一、微服务与单体项目文档整合的区别二、开始整合1. 搭建一个父子maven模块的微服务,并引入gateway2.开始整合文档 总结 knife4j 微服务整合 由于单个服务的knife4j 整合之前已经写过了,那么由于效果比较好,然后微服务的项目中也想引入,所以开始微…...

ASP.NET 记录 HttpRequest HttpResponse HttpServerUtility
纯属个人记录,会有错误 HttpRequest Browser是获取客户端浏览器的信息 Cookies是获取客户端的Cookies QueryString是获取客户端提交的数据 ServerVariables是获取服务器端或客户端的环境变量信息 Browser 语法格式: Request.Browser[“浏览器特性名”] 常见的特性名 名称说…...
Python 人工智能:11~15
原文:Artificial Intelligence with Python 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自【ApacheCN 深度学习 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。 不要担心自己的形象,只关心如何…...

辉煌优配|军工板块逆市上涨,16只概念股已披露一季度业绩预喜
今日,军工股逆市上涨。 4月21日,A股三大股指低开低走,半导体、AI使用、信创工业、软件等科技属性概念领跌,国防军工、食品饮料和电力设备等板块上涨。 工业互联网中心工业规模超1.2万亿元 据央视新闻报道,本年是《工业…...

看板与 Scrum:有什么区别?
看板和Scrum是项目管理方法论,以小增量完成项目任务并强调持续改进。但是他们用来实现这些目标的过程是不同的。看板以可视化任务和连续流程为中心,而Scrum更多是关于为每个交付周期实施时间表和分配设定角色。 在看板和Scrum之间做出选择并不总是必要…...

零代码是什么?零代码平台适合谁用?
随着信息技术的发展,软件开发领域也不断发生变革,零代码(No-Code)开发模式越来越受到关注。 零代码到底是什么,能不能用通俗的话来说?这就来给大家讲一讲! 01 零代码为什么出现? 随…...

CNStack 云服务云组件:打造丰富的云原生技术中台生态
作者:刘裕惺 CNStack 相关阅读: CNStack 多集群服务:基于OCM 打造完善的集群管理能力 CNStack 虚拟化服务:实现虚拟机和容器资源的共池管理 CNStack 云边协同平台:实现原生边缘竟能如此简单 01 前言 CNStack 2.0…...
#PythonPytorch 1.如何入门深度学习模型
我之前也写过一篇关于Keras的深度学习入门blog,#Python&Keras 1.如何从无到有在自己的数据集上实现深度学习模型(入门),里面也有介绍了一下一点点机器学习的概念和理解深度学习的输入,如果对这方面有疑惑的朋友可以…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...

Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...

Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...