专栏名称: Java基基
一个苦练基本功的 Java 公众号,所以取名 Java 基基
目录
相关文章推荐
航空工业  ·  TP500无人机2002架首飞成功 ·  12 小时前  
航空工业  ·  历经2000余架次、3000余小时、1000 ... ·  12 小时前  
航空工业  ·  岁月鎏金映初心 温情长伴启新程 ... ·  昨天  
航空工业  ·  这里,攻坚战正酣! ·  2 天前  
51好读  ›  专栏  ›  Java基基

如何用 Java Stream 写出 “高效率、干净、简洁” 的代码?

Java基基  · 公众号  ·  · 2025-01-01 13:19

主要观点总结

本文介绍了Java流式编程的相关内容,包括创建流的方式、流的中间操作和终端操作,以及常见的流操作如过滤、映射、排序、去重等。文章还提到了使用Java流处理集合的方法,如转为List、Set、Map等,并介绍了流的截断、跳过、观察等操作。最后,给出了关于如何创建流、使用流进行数据处理的相关代码示例,并提供了加入知识星球的邀请。

关键观点总结

关键观点1: Java流式编程概述

介绍了Java流式编程的概念,以及它如何帮助Java程序员以声明的方式处理数据。

关键观点2: 流的创建方式

讲解了通过集合创建流的方式,包括串行流和并行流的创建。

关键观点3: 流的中间操作

详细解释了流的过滤、映射、排序、去重等中间操作,并给出了相关代码示例。

关键观点4: 流的终端操作

介绍了流的迭代操作、收集操作以及其他终端操作,如findFirst、findAny、anyMatch、noneMatch和allMatch等。

关键观点5: 知识星球邀请

文章结尾处提供了加入知识星球的邀请,内容涵盖项目实战、面试招聘、源码解析、学习路线等。


正文

👉 这是一个或许对你有用 的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入 芋道快速开发平台 知识星球。 下面是星球提供的部分资料:

👉 这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号等等功能:

  • Boot 仓库:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 仓库:https://gitee.com/zhijiantianya/yudao-cloud
  • 视频教程:https://doc.iocoder.cn
【国内首批】支持 JDK 21 + SpringBoot 3.2.2、JDK 8 + Spring Boot 2.7.18 双版本

来源:juejin.cn/post/
7344026980616077350


Java 常见的Stream流式编程

  • Java 8 添加了一个新的抽象称为流 Stream API,可以让你以一种声明的方式处理数据。
  • Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
  • Stream API 可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

如何创建流?

集合创建:
  • stream() − 为集合创建串行流。在串行流中,每个元素都是由同一个线程处理的,因此操作是顺序执行的。
  • parallelStream() − 为集合创建并行流。在并行流中,流会将集合分成多个子集,然后多线程并行处理这些子集中的元素。
/**
* 集合创建流
*/

List list = new ArrayList<>();
//串行流
Stream stream = list.stream();
//并行流
Stream stream = list.parallelStream();
数组创建:

通过数组创建的方式有: Stream.of() Stream.generate() Stream.iterate() IntStream LongStream 等,如下代码。

/**
* 数组创建流
*/

String[] strs = new String[3];
Stream stream1 = Arrays.stream(strs);

/**
* Stream.of() 创建流
*/

Stream stream2 = Stream.of("Apple""Orange""Banana");

/**
* Stream.generate()创建流
*/

Stream randomStream = Stream.generate(Math::random).limit(5);

/**
* Stream.iterate()创建流
*/

Stream integerStream = Stream.iterate(0, n -> n + 2).limit(5);

/**
* IntStream创建流
*/

IntStream intStream = IntStream.range(15); // [1,2,3,4]

/**
* LongStream创建流
*/

LongStream longStream = LongStream.rangeClosed(15); // [1,2,3,4,5]

通常,我们遍历一个集合时会使用 for(int i = 0; i < list.size(); i++) 这种方式,但是当我们有 IntStream 可用时,可以优化为使用 IntStream.rangeClosed(0, list.size() - 1).forEach(i -> {...}) 来遍历集合。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

中间操作

过滤操作(filter)

过滤操作,可以保留满足过滤条件的元素。如下代码为:将 lists 流中的等于 1 的元素过滤出来,并打印结果。

/**
* filter 过滤操作
@param lists
*/

public static void filterTest(List lists){
 List integers = lists.stream()
        .filter(list ->Objects.equals(1, list)).toList();
 integers.forEach(System.out::println);
}
映射操作(map / flatMap)

映射操作,可以对流中的每个元素提取并转换。如下代码为:

  • map 映射操作: 将 lists 流中的字符串,处理成大写的字符串;
  • flatMap 映射操作: 将 lists 流中的二位数组,转成一维数组。(flatMap 用于将流中的一个元素转换为一个流,然后将所有转换后的流组装成一个流)
/**
* map映射操作
*/

public static void mapTest(List lists){
 lists.stream().map(String::toLowerCase).toList();
 lists.forEach(System.out::println);
}

/**
* flatMap映射操作,将嵌套集合转换为扁平集合
*/

public static void flatMapTest(List> lists){
 lists = Arrays.asList(
  Arrays.asList("Java""Kotlin"),
  Arrays.asList("Python""Ruby"),
  Arrays.asList("JavaScript""TypeScript")
 );
 List wordList = lists.stream().flatMap(List::stream).toList();
 wordList.forEach(System.out::println);
}
mapToInt / mapToLong / mapToDouble 操作

mapToInt / mapToLong / mapToDouble 操作,可以将流中的元素映射为对应 int / Long / Double 类型,并进一步做数值计算。

public class Student{
    //年龄
    private int age;
    //姓名
    private String Name;
}
public static void mapTest(){
    int totalAge1 = students.stream().mapToInt(Student::getAge).sum();
    Long totalAge2 = students.stream().mapToLong(Student::getAge).sum();
    Double totalAge3 = students.stream().mapToDouble(Student::getAge).sum();
}
排序操作(sorted)

排序流中的元素。

/**
* 排序操作 sorted,对于集合对象排序,必须实现 Comparable接口,并重写 compareTo 方法,如果没有实现则需要给 sorted 函数传递参数
*/

public static void sortedTest(){
 List cities = Arrays.asList("New York""Tokyo""London""Paris");
 // 对城市按字母顺序排序
 List sortedStream = cities.stream().sorted(Comparator.comparingInt(city -> city.charAt(1))).toList();
 sortedStream.forEach(System.out::println);
}
去重操作(distinct)

去除流中的重复元素。

/**
* 去重操作(distinct)
*/

public static void distinctTest(){
 List cities = Arrays.asList("New York""Tokyo""London""Paris");
 // 对城市去重
 List distinctStream = cities.stream().distinct();
 sortedStream.forEach(System.out::println);
}
截断操作 / 跳过操作 / 观察操作(limit / skip / peek)
/**
* 截断操作(limit),只取流中前3个元素
*/

List numbers = Lists.newArrayList(123456); 
List limitedList = numbers.stream().limit(3).collect(Collectors.toList());

/**
* 跳过操作(skip),跳过流中前3个元素
*/

List numbers = Lists.newArrayList(123456); 
List limitedList = numbers.stream().skip(3).collect(Collectors.toList());

/**
* 观察操作,用于调试和观察流中的元素
*/

List words = Arrays.asList("apple""banana""orange");  
List modifiedWords = words.stream()  
        .filter(word -> word.length() > 5)  
        .peek(word -> System.out.println("Filtered Word: " + word))  
        .map(String::toUpperCase)  
        .peek(word -> System.out.println("Uppercase Word: " + word))  
        .collect(Collectors.toList());

终端操作

迭代操作(forEach)

迭代操作,可以用于遍历流中的每一个元素。

List fruits = Arrays.asList("apple""banana""orange");
fruits.stream().forEach(fruit -> System.out.println(fruit));
//fruits.forEach(fruit -> System.out.println(fruit));
//fruits.stream().forEach(System.out::println);
收集操作(collect)

收集操作,可以将流转换为 List、Set、Map 等集合。通过 collect 函数,对流中的元素进行收集。

// 将学生流转换为 List
List limitStu = students.stream().collect(Collectors.toList());

// 将学生流转换为 Set
List limitStu = students.stream().collect(Collectors.toSet());

// 将学生流转换为 Map,将年龄作为 key,将学生信息作为 value (Function.identity() 为提取元素自身的函数,(e1, e2)-> e1 代表当两个学生年龄相同时,取第一个学生)
Map studentMap = students.stream().collect(Collectors.toMap(
           Student::getAge, 
           Function.identity(), 
           (e1,e2) -> e1));

//将学生的名字通过逗号拼接成一个字符串:studentName
String studentName = students.stream().map(Student::getName).collect(Collectors.joining(","));

//通过字符串的长度对 fruits 流分组
List fruits = Arrays.asList("apple""banana""orange");  
Map> lengthToNamesMap = fruits.stream()  
                    .collect(Collectors.groupingBy(String::length));






请到「今天看啥」查看全文