[Java] Stream流使用最多的方式

Java 中 Stream 流的用法全解析

在 Java 编程中,Stream 流提供了一种高效、便捷的方式来处理集合数据。它可以让我们以声明式的方式对数据进行各种操作,如过滤、映射、排序、聚合等,大大简化了数据处理的代码编写。本文将详细介绍 Java 中 Stream 流的用法,包括基础用法、中级用法、高级用法以及一些特殊方法的使用。

一、基础用法

1. 创建 Stream

  • 从集合创建 Stream :通过调用集合的 stream() 方法可以创建一个顺序流。例如:

    List<String> list = Arrays.asList("apple", "banana", "cherry");
    Stream<String> stream1 = list.stream();

  • 从数组创建 Stream :使用 Arrays.stream() 方法可以从数组创建流。例如:

    String[] array = {"apple", "banana", "cherry"};
    Stream<String> stream2 = Arrays.stream(array);

2. 中间操作

  • filter:过滤元素 :使用 filter 方法可以根据指定的条件过滤流中的元素。例如,以下代码过滤出以 "a" 开头的字符串:

    list.stream()
    .filter(s -> s.startsWith("a"))
    .forEach(System.out::println); // 输出: apple

  • map:转换元素map 方法可以将流中的每个元素按照指定的函数进行转换。例如,将字符串转换为大写:

    list.stream()
    .map(String::toUpperCase)
    .forEach(System.out::println); // 输出: APPLE BANANA CHERRY

3. 终止操作

  • forEach:遍历元素forEach 方法用于遍历流中的每个元素并执行指定的操作。例如:

    list.stream().forEach(System.out::println);

  • collect:收集结果到集合collect 方法可以将流中的元素收集到指定的集合中。例如,收集长度大于 5 的字符串到一个新的列表中:

    List<String> result1 = list.stream()
    .filter(s -> s.length() > 5)
    .collect(Collectors.toList());

    // 或者使用 toList() 方法(Java 16 及以上版本)
    List<String> result2 = list.stream()
    .filter(s -> s.length() > 5)
    .toList();

二、中级用法

1. 排序

  • sorted:自然排序或自定义排序sorted 方法可以对流中的元素进行排序。如果元素实现了 Comparable 接口,可以直接使用无参的 sorted 方法进行自然排序。例如:

    list.stream()
    .sorted()
    .forEach(System.out::println); // 输出: apple banana cherry

如果需要自定义排序规则,可以传入一个 Comparator 比较器。例如,按照字符串长度倒序排序:

复制代码
list.stream()
  .sorted(Comparator.reverseOrder())
  .forEach(System.out::println); // 输出: cherry banana apple

2. 去重

使用 distinct 方法可以去除流中的重复元素。例如:

复制代码
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
List<Integer> distinctNumbers = numbers.stream()
  .distinct()
  .toList();

3. 聚合操作

  • reduce:归约操作reduce 方法可以对流中的元素进行归约操作,例如求和、求乘积等。例如,计算整数列表的总和:

    Optional<Integer> sum = numbers.stream()
    .reduce((a, b) -> a + b); // 可替换为.reduce(Integer::sum);
    System.out.println(sum.get()); // 输出: 19

三、高级用法

1. 并行流

  • parallelStream:并行处理(提高效率) :使用 parallelStream 方法可以创建一个并行流,它会在多个线程上并行处理流中的元素,提高处理效率。例如,计算满足条件的元素数量:

    long count = list.parallelStream()
    .filter(s -> s.length() > 5)
    .count();

2. 短路操作

  • anyMatch、allMatch、noneMatch:短路匹配 :这些方法用于在流中进行短路匹配操作。anyMatch:只要流中有一个元素满足条件就返回true。例如:

    boolean anyStartsWithA = list.stream()
    .anyMatch(s -> s.startsWith("a"));
    System.out.println(anyStartsWithA); // 输出: true

  • allMatch:只有流中所有元素都满足条件才返回 true。例如:

    boolean allStartsWithA = list.stream()
    .allMatch(s -> s.startsWith("a"));
    System.out.println(allStartsWithA); // 输出: false

  • noneMatch:如果流中没有元素满足条件则返回 true。例如:

    boolean noneStartsWithZ = list.stream()
    .noneMatch(s -> s.startsWith("z"));
    System.out.println(noneStartsWithZ); // 输出: true

3. 分组和分区

  • Collectors.groupingBy:分组 :使用 groupingBy 方法可以根据指定的分类函数将流中的元素分组到一个 Map 中。例如,根据字符串的首字母进行分组:

    Map<Character, List<String>> groupedByFirstLetter = list.stream()
    .collect(Collectors.groupingBy(s -> s.charAt(0)));
    System.out.println(groupedByFirstLetter); // {a=[apple], b=[banana], c=[cherry]}

  • Collectors.partitioningBy:分区partitioningBy 方法根据指定的布尔条件将流中的元素分区到一个 Map 中,键为 truefalse。例如,根据字符串长度是否大于 5 进行分区:

    Map<Boolean, List<String>> partitioned = list.stream()
    .collect(Collectors.partitioningBy(s -> s.length() > 5)); // {false=[apple], true=[banana, cherry]}
    System.out.println(partitioned);

4. 收集到 Map

  • Collectors.toMap:收集到 Map :使用 toMap 方法可以将流中的元素收集到一个 Map 中,需要指定键和值的映射函数。例如:

    Map<String, Integer> map = list.stream()
    .collect(Collectors.toMap(Function.identity(), String::length));
    System.out.println(map);

四、flatMap 用法

flatMap

方法用于将流中的每个元素转换为另一个流,然后将这些流扁平化成一个单一的流。这在处理嵌套集合时非常有用。例如:

复制代码
List<List<String>> listOfLists = Arrays.asList(
    Arrays.asList("apple", "banana"),
    Arrays.asList("cherry", "date"),
    Arrays.asList("fig", "grape")
);

// 使用 flatMap 将嵌套列表扁平化
List<String> flattenedList = listOfLists.stream()
  .flatMap(List::stream)
  .collect(Collectors.toList());

System.out.println(flattenedList); // 输出: [apple, banana, cherry, date, fig, grape]

五、peek 用法

  • peek 方法主要用于调试,它允许你在流的每个元素上执行某个操作(例如打印),而不会改变流中的元素。peek 返回一个新的流,其中包含与原始流相同的元素。例如:

    List<String> list = Arrays.asList("apple", "banana", "cherry");

    List<String> result = list.stream()
    .peek(s -> System.out.println("Processing: " + s)) // 打印每个元素
    .map(String::toUpperCase)
    .collect(Collectors.toList());

    System.out.println(result); // 输出: [APPLE, BANANA, CHERRY]

六、limit 用法

  • limit 方法用于限制流中的元素数量。例如:

    List<String> list = Arrays.asList("apple", "banana", "cherry", "date", "fig", "grape");

    List<String> limitedList = list.stream()
    .limit(3)
    .collect(Collectors.toList());

    System.out.println(limitedList); // 输出: [apple, banana, cherry]

七、skip 用法

  • skip 方法用于跳过流中的前 n 个元素。例如:

    List<String> list = Arrays.asList("apple", "banana", "cherry", "date", "fig", "grape");

    List<String> skippedList = list.stream()
    .skip(3)
    .collect(Collectors.toList());

    System.out.println(skippedList); // 输出: [date, fig, grape]

八、min 和 max

  • minmax 方法用于查找流中的最小值和最大值。例如:

    List<Integer> numbers = Arrays.asList(10, 20, 30, 40, 50);

    // 查找最小值
    Optional<Integer> min = numbers.stream()
    .min(Integer::compareTo);

    System.out.println(min.get()); // 输出: 10

    // 查找最大值
    Optional<Integer> max = numbers.stream()
    .max(Integer::compareTo);

    System.out.println(max.get()); // 输出: 50

九、findAny 和 findFirst

  • findAnyfindFirst 方法用于查找流中的任意元素和第一个元素。例如:

    List<String> list = Arrays.asList("apple", "banana", "cherry");

    // 查找任意一个元素
    Optional<String> anyElement = list.stream().findAny();

    System.out.println(anyElement.get()); // 输出: apple (或 banana 或 cherry)

    // 查找第一个元素
    Optional<String> firstElement = list.stream().findFirst();

    System.out.println(firstElement.get()); // 输出: apple

通过以上对 Java 中 Stream 流的全面介绍,我们可以看到它在数据处理方面提供了强大而灵活的功能。合理运用 Stream 流可以使我们的代码更加简洁、高效,提高编程的效率和代码的可读性。在实际开发中,根据具体的需求选择合适的 Stream 流操作方法,可以更好地处理集合数据,实现复杂的数据处理逻辑。

文章转载自: ++佛祖让我来巡山++

原文链接: https://www.cnblogs.com/sun-10387834/p/18601174

体验地址: 引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

相关推荐
好奇的菜鸟1 小时前
如何在IntelliJ IDEA中设置数据库连接全局共享
java·数据库·intellij-idea
程序视点1 小时前
Window 10文件拷贝总是卡很久?快来试试这款小工具,榨干硬盘速度!
windows
wuk9982 小时前
基于MATLAB编制的锂离子电池伪二维模型
linux·windows·github
DuelCode2 小时前
Windows VMWare Centos Docker部署Springboot 应用实现文件上传返回文件http链接
java·spring boot·mysql·nginx·docker·centos·mybatis
优创学社22 小时前
基于springboot的社区生鲜团购系统
java·spring boot·后端
幽络源小助理2 小时前
SpringBoot基于Mysql的商业辅助决策系统设计与实现
java·vue.js·spring boot·后端·mysql·spring
猴哥源码2 小时前
基于Java+springboot 的车险理赔信息管理系统
java·spring boot
烛阴3 小时前
简单入门Python装饰器
前端·python
lzb_kkk3 小时前
【C++】C++四种类型转换操作符详解
开发语言·c++·windows·1024程序员节
YuTaoShao3 小时前
【LeetCode 热题 100】48. 旋转图像——转置+水平翻转
java·算法·leetcode·职场和发展