系列学习 Lambda 表达式之第 2 篇 —— JDK1.8 的 Stream 流基本使用
查看之前的博客可以点击顶部的【分类专栏】
什么是 Stream?
Stream 是 JDK1.8 中处理集合的关键抽象概念。Lambda 和 Stream 是 JDK1.8 新增的函数式编程最优亮点的特性。它可以对集合进行查找、过滤、排序和映射数据等操作。类似于使用 SQL 执行数据库查询语句一样。Stream API 可以让程序员写出高效率、干净、简洁的代码。
说明:使用终止操作的关键字,是不允许再使用中间操作的关键字了。也就是说,如果使用了 forEach、collect、min、max等终止操作,则不能在后面使用 filter 等中间操作了。
Stream 流有串行流 stream() 和并行流 parallelStream() 之分。并行流表示多线程的,效率高一点。
使用 Stream 流将List 转成 Set 集合
public class Test2 {public static void main(String[] args) {List<UserInfo> list = new ArrayList<>();list.add(new UserInfo("张三",13));list.add(new UserInfo("李四",14));list.add(new UserInfo("王五",15));list.add(new UserInfo("朱六",16));list.add(new UserInfo("朱六",16));//并行流,效率高一点//list.parallelStream();//创建一个串行流Stream<UserInfo> stream = list.stream();//转换成 Set 集合Set<UserInfo> set = stream.collect(Collectors.toSet());set.forEach(p ->{System.out.println(p.toString());});}static class UserInfo {private String userName;private Integer age;public UserInfo(String userName, Integer age) {this.userName = userName;this.age = age;}@Overridepublic String toString() {return "UserInfo{" +"userName='" + userName + '\'' +", age=" + age +'}';}}}
我们现在把 List 转成 Set 集合,在JDK1.8 之前,我们需要 for 循环,然后一个个的放入 Set 集合里。现在不需要了。直接以下使用方法即可:
Stream<UserInfo> stream = list.stream();Set<UserInfo> set = stream.collect(Collectors.toSet());set.forEach(p ->{System.out.println(p.toString());});
输出(注意两个朱六,因为是使用 new 的方式创建,它们的地址引用是不同的,因此是2个对象,hashCode 不一样):
UserInfo{userName='李四', age=14}
UserInfo{userName='王五', age=15}
UserInfo{userName='朱六', age=16}
UserInfo{userName='张三', age=13}
UserInfo{userName='朱六', age=16}
我们重写 UserInfo 实体的 equals 和 hashCode 方法:(IDEA 下按 Alt+INSERT,调出快捷键)
@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;UserInfo userInfo = (UserInfo) o;return Objects.equals(userName, userInfo.userName) &&Objects.equals(age, userInfo.age);}@Overridepublic int hashCode() {return Objects.hash(userName, age);}
然后重新运行,输出:
UserInfo{userName='朱六', age=16}
UserInfo{userName='张三', age=13}
UserInfo{userName='李四', age=14}
UserInfo{userName='王五', age=15}
使用 Stream 流将 List 集合转换成 Map
public class Test3 {public static void main(String[] args) {List<UserInfo> list = new ArrayList<>();list.add(new UserInfo("张三", 13));list.add(new UserInfo("李四", 14));list.add(new UserInfo("王五", 15));list.add(new UserInfo("朱六", 16));//创建 Stream 流Stream<UserInfo> stream = list.stream();//转成 Map 集合,其中 key 为用户名,value 为实体Map<String, UserInfo> map = stream.collect(Collectors.toMap(info -> info.getUserName(), info -> info));map.forEach((BiConsumer) (p1, p2) -> {System.out.println("key=" + p1 + ",value=" + p2);});}static class UserInfo {private String userName;private Integer age;public UserInfo(String userName, Integer age) {this.userName = userName;this.age = age;}@Overridepublic String toString() {return "UserInfo{" +"userName='" + userName + '\'' +", age=" + age +'}';}public String getUserName() {return userName;}}
}
输出:
key=朱六,value=UserInfo{userName='朱六', age=16}
key=李四,value=UserInfo{userName='李四', age=14}
key=张三,value=UserInfo{userName='张三', age=13}
key=王五,value=UserInfo{userName='王五', age=15}
使用 Stream 流查询最大、最小的元素
public class Test4 {public static void main(String[] args) {List<UserInfo> list = new ArrayList<>();list.add(new UserInfo("张三", 13));list.add(new UserInfo("李四", 14));list.add(new UserInfo("王五", 15));list.add(new UserInfo("朱六", 16));//创建 Stream 流Stream<UserInfo> stream = list.stream();//最大的年龄Optional<UserInfo> max = stream.max((m1,m2) -> m1.getAge() - m2.getAge());System.out.println(max.get());//最小的年龄//创建 Stream 流Stream<UserInfo> stream2 = list.stream();Optional<UserInfo> min = stream2.min((m1,m2) -> m1.getAge() - m2.getAge());System.out.println(min.get());}static class UserInfo {private String userName;private Integer age;public UserInfo(String userName, Integer age) {this.userName = userName;this.age = age;}@Overridepublic String toString() {return "UserInfo{" +"userName='" + userName + '\'' +", age=" + age +'}';}public Integer getAge() {return age;}}
}
注意:Stream 流使用一次后,就会释放资源,如果想要二次使用,需要重新创建。否则报错:
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
输出:
UserInfo{userName='朱六', age=16}
UserInfo{userName='张三', age=13}
使用 Stream 的 Match 匹配
public class Test5 {public static void main(String[] args) {List<UserInfo> list = new ArrayList<>();list.add(new UserInfo("张三", 13));list.add(new UserInfo("李四", 14));list.add(new UserInfo("王五", 15));list.add(new UserInfo("朱六", 16));//创建 Stream 流Stream<UserInfo> stream = list.stream();boolean flag = stream.anyMatch(m -> "张三".equals(m.getUserName()));System.out.println(flag);}static class UserInfo {private String userName;private Integer age;public UserInfo(String userName, Integer age) {this.userName = userName;this.age = age;}@Overridepublic String toString() {return "UserInfo{" +"userName='" + userName + '\'' +", age=" + age +'}';}public String getUserName() {return userName;}}
}
anyMatch 是返回任何一条匹配的即可。
输出:
true
使用 Stream 过滤器 Filter
public class Test6 {public static void main(String[] args) {List<UserInfo> list = new ArrayList<>();list.add(new UserInfo("张三", 13));list.add(new UserInfo("李四", 14));list.add(new UserInfo("王五", 15));list.add(new UserInfo("朱六", 16));list.add(new UserInfo("朱六", 20));//创建 Stream 流Stream<UserInfo> stream = list.stream();//过滤名字是【朱六】,且年龄大于18岁的stream.filter(m -> "朱六".equals(m.getUserName()) && m.getAge() > 18).forEach(m -> System.out.println(m));}static class UserInfo {private String userName;private Integer age;public UserInfo(String userName, Integer age) {this.userName = userName;this.age = age;}@Overridepublic String toString() {return "UserInfo{" +"userName='" + userName + '\'' +", age=" + age +'}';}public String getUserName() {return userName;}public Integer getAge() {return age;}}
}
输出:
UserInfo{userName='朱六', age=20}
使用 Stream 流分页 limit
public class Test7 {public static void main(String[] args) {List<UserInfo> list = new ArrayList<>();list.add(new UserInfo("张三", 13));list.add(new UserInfo("李四", 14));list.add(new UserInfo("王五", 15));list.add(new UserInfo("朱六", 16));list.add(new UserInfo("朱六", 20));//创建 Stream 流Stream<UserInfo> stream = list.stream();//取出前2条stream.limit(2).forEach(m -> System.out.println(m));}static class UserInfo {private String userName;private Integer age;public UserInfo(String userName, Integer age) {this.userName = userName;this.age = age;}@Overridepublic String toString() {return "UserInfo{" +"userName='" + userName + '\'' +", age=" + age +'}';}}
}
输出:
UserInfo{userName='张三', age=13}
UserInfo{userName='李四', age=14}
如果想从第3条开始获取呢?使用 skip 跳过,如下:
stream.skip(2).limit(3).forEach(m -> System.out.println(m));
输出:(如果 limit 的数字超过了 list 集合的长度,不会抛异常。)
UserInfo{userName='王五', age=15}
UserInfo{userName='朱六', age=16}
UserInfo{userName='朱六', age=20}
使用 Stream 排序 sort
按照年龄升序:
public class Test8 {public static void main(String[] args) {List<UserInfo> list = new ArrayList<>();list.add(new UserInfo("张三", 13));list.add(new UserInfo("李四", 14));list.add(new UserInfo("王五", 15));list.add(new UserInfo("朱六", 16));list.add(new UserInfo("朱六", 20));//创建 Stream 流Stream<UserInfo> stream = list.stream();stream.sorted((m1, m2) -> m1.getAge() - m2.getAge()).forEach(k -> System.out.println(k));}static class UserInfo {private String userName;private Integer age;public UserInfo(String userName, Integer age) {this.userName = userName;this.age = age;}@Overridepublic String toString() {return "UserInfo{" +"userName='" + userName + '\'' +", age=" + age +'}';}public Integer getAge() {return age;}}
}
输出:
UserInfo{userName='张三', age=13}
UserInfo{userName='李四', age=14}
UserInfo{userName='王五', age=15}
UserInfo{userName='朱六', age=16}
UserInfo{userName='朱六', age=20}
如果需要降序排,则使用 m2 - m1 即可,如:
//创建 Stream 流Stream<UserInfo> stream = list.stream();stream.sorted((m1, m2) -> m2.getAge() - m1.getAge()).forEach(k -> System.out.println(k));
输出:
UserInfo{userName='朱六', age=20}
UserInfo{userName='朱六', age=16}
UserInfo{userName='王五', age=15}
UserInfo{userName='李四', age=14}
UserInfo{userName='张三', age=13}
系列学习 Lambda 表达式之第 2 篇 —— JDK1.8 的 Stream 流基本使用相关推荐
- jdk8新特性(接口新特性、lambda表达式、方法引用、函数式接口、Stream流)和单例设计模式
1.单例设计模式 1.概念: 设计模式:使用固有的流程或方式设计出来的类接口.枚举等元素 2.设计原则: 1.私有化构造方法[private.protected] 2.类中创建最终对象[唯一不能被赋值 ...
- Java8新特性学习_001_(Lambda表达式,函数式接口,方法引用,Stream类,Optional类)
目录 ■代码 ■代码运行结果 ■代码说明 ・44行:Stream的.foreach方法ー参数类型:函数式接口 ・82行:Interface中,default方法 ・92行 Stream的.max方 ...
- java 1.8stream_java jdk1.8 使用stream流进行list 分组归类操作
我就废话不多说了,大家还是直接看代码吧~ import com.alibaba.fastjson.JSON; import java.util.ArrayList; import java.util. ...
- JDK1.8 Java8 Stream流 认知以及常见使用
注意前提条件: 环境一定是JDK1.8 现在大部分都是1.8的环境,同样也要学习.使用.对其认知,可以使我们开发效率提高,不至于别人请教的时候不清楚. /*** @ClassName User* @D ...
- java junit 异常_JUnit:使用Java 8和Lambda表达式测试异常
java junit 异常 在JUnit中,有许多方法可以在测试代码中测试异常,包括try-catch idiom JUnit @Rule和catch-exception库. 从Java 8开始,我们 ...
- JUnit:使用Java 8和Lambda表达式测试异常
在JUnit中,有许多方法可以在测试代码中测试异常,包括try-catch idiom JUnit @Rule和catch-exception库. 从Java 8开始,我们还有另一种处理异常的方法:使 ...
- 学习笔记之-java8的新特性-函数式接口,lambda表达式,方法引用,Stream API,Optional类
1.Lambda表达式 用匿名内部类的方法去创建多线程1.new Thread2.参数传递new Runnable3.重写run方法4.在run方法中去设置线程任务5.调用start问题:我们最终目标 ...
- lambda表达式最全总结
lambda表达式 一.lambda表达式的引入 为什么引入lambda表达式 需求环境:线程类的创建 解决方案:匿名内部类实现 解决方案PLUS:lambda表达式实现 代码: package co ...
- Lambda表达式超详细总结
文章目录 1. 什么是Lambda表达式 2. 为什么使用Lambda表达式 3. Lambda表达式语法 4. 函数式接口 4.1 什么是函数式接口 4.2 自定义函数式接口 4.3 Java内置函 ...
- Lambda和Stream流
目录 需要笔记的可以关注私聊,我发给你 Lambda 格式 排序 Stream流 获取流: .stream( ) 操作流(中间方法): 终结流: 收集流的操作 第一部分 第二部分 第三部分 Optio ...
最新文章
- kafka 监控(eagle)
- PHP MVC框架核心类
- Oracle的分区操持
- ASP.NET Core 新核心对象WebHost(一)
- 面试题及答案_NET
- 2_6 CompositeMode.cpp 组合模式
- 【英语学习】【Level 08】U05 Better option L3 Everything's a click away
- 算法工程师面试备战笔记8_猜测这种划分最可能是什么聚类算法的结果
- [转] Spring XML配置十二个最佳实践
- protel99se基本教程及使用教程
- Java随机数的使用
- 删除表记录(delete from where )
- vue中使用web serial api实现串口通信
- 关于coutends你不知道的那些事
- 如何画一块标准的PCB板?SMT工艺PCB要求
- 图形界面 I: 图形界面的动画 (第三章)
- oracle条件查询数量统计,Oracle多条件的统计查询(case when)
- 一文轻松掌握python语言命名规则(规范)
- Linux系统yum源的三种配置方法
- XTU 1256 湘潭大学