查看之前的博客可以点击顶部的【分类专栏】

什么是 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 流基本使用相关推荐

  1. jdk8新特性(接口新特性、lambda表达式、方法引用、函数式接口、Stream流)和单例设计模式

    1.单例设计模式 1.概念: 设计模式:使用固有的流程或方式设计出来的类接口.枚举等元素 2.设计原则: 1.私有化构造方法[private.protected] 2.类中创建最终对象[唯一不能被赋值 ...

  2. Java8新特性学习_001_(Lambda表达式,函数式接口,方法引用,Stream类,Optional类)

    目录 ■代码 ■代码运行结果 ■代码说明 ・44行:Stream的.foreach方法ー参数类型:函数式接口 ・82行:Interface中,default方法 ・92行   Stream的.max方 ...

  3. java 1.8stream_java jdk1.8 使用stream流进行list 分组归类操作

    我就废话不多说了,大家还是直接看代码吧~ import com.alibaba.fastjson.JSON; import java.util.ArrayList; import java.util. ...

  4. JDK1.8 Java8 Stream流 认知以及常见使用

    注意前提条件: 环境一定是JDK1.8 现在大部分都是1.8的环境,同样也要学习.使用.对其认知,可以使我们开发效率提高,不至于别人请教的时候不清楚. /*** @ClassName User* @D ...

  5. java junit 异常_JUnit:使用Java 8和Lambda表达式测试异常

    java junit 异常 在JUnit中,有许多方法可以在测试代码中测试异常,包括try-catch idiom JUnit @Rule和catch-exception库. 从Java 8开始,我们 ...

  6. JUnit:使用Java 8和Lambda表达式测试异常

    在JUnit中,有许多方法可以在测试代码中测试异常,包括try-catch idiom JUnit @Rule和catch-exception库. 从Java 8开始,我们还有另一种处理异常的方法:使 ...

  7. 学习笔记之-java8的新特性-函数式接口,lambda表达式,方法引用,Stream API,Optional类

    1.Lambda表达式 用匿名内部类的方法去创建多线程1.new Thread2.参数传递new Runnable3.重写run方法4.在run方法中去设置线程任务5.调用start问题:我们最终目标 ...

  8. lambda表达式最全总结

    lambda表达式 一.lambda表达式的引入 为什么引入lambda表达式 需求环境:线程类的创建 解决方案:匿名内部类实现 解决方案PLUS:lambda表达式实现 代码: package co ...

  9. Lambda表达式超详细总结

    文章目录 1. 什么是Lambda表达式 2. 为什么使用Lambda表达式 3. Lambda表达式语法 4. 函数式接口 4.1 什么是函数式接口 4.2 自定义函数式接口 4.3 Java内置函 ...

  10. Lambda和Stream流

    目录 需要笔记的可以关注私聊,我发给你 Lambda 格式 排序 Stream流 获取流: .stream( ) 操作流(中间方法): 终结流: 收集流的操作 第一部分 第二部分 第三部分 Optio ...

最新文章

  1. kafka 监控(eagle)
  2. PHP MVC框架核心类
  3. Oracle的分区操持
  4. ASP.NET Core 新核心对象WebHost(一)
  5. 面试题及答案_NET
  6. 2_6 CompositeMode.cpp 组合模式
  7. 【英语学习】【Level 08】U05 Better option L3 Everything's a click away
  8. 算法工程师面试备战笔记8_猜测这种划分最可能是什么聚类算法的结果
  9. [转] Spring XML配置十二个最佳实践
  10. protel99se基本教程及使用教程
  11. Java随机数的使用
  12. 删除表记录(delete from where )
  13. vue中使用web serial api实现串口通信
  14. 关于coutends你不知道的那些事
  15. 如何画一块标准的PCB板?SMT工艺PCB要求
  16. 图形界面 I: 图形界面的动画 (第三章)
  17. oracle条件查询数量统计,Oracle多条件的统计查询(case when)
  18. 一文轻松掌握python语言命名规则(规范)
  19. Linux系统yum源的三种配置方法
  20. XTU 1256 湘潭大学

热门文章

  1. Javascript es6 在线编辑器
  2. 波兰表达式和逆波兰表达式
  3. 小米5s安装xpose 上
  4. Laravel 邮件
  5. unity之EasyAR使用
  6. POST 请求的四种提交数据方式
  7. centos freeradius mysql_CentOS 5.7安装FreeRADIUS 1.1.3+MySQL 5.0.77结合RouteOS
  8. dnf时装补丁教程_【时装补丁制作】消灭伸手党!最详细的图文教程~
  9. 基于SpringBoot的抽奖系统
  10. ACM程序设计大赛简介