【Java】Stream API 全面详解

大家好,今天继续分享 Java 相关知识点,本篇来详细讲解 Stream API。Stream 是 Java 8 引入的核心特性之一,借助它我们可以用更简洁、优雅的方式处理集合、数组等数据源,告别繁琐的循环遍历,让代码可读性大幅提升。

一、什么是 Stream

Stream 可以理解为高级迭代器,它有几个核心特点:

  1. 只能遍历一次,遍历结束后流就会被销毁,无法重复使用;
  2. 操作流必须依托数据源,常见数据源为数组、集合;
  3. Stream 支持链式调用,每一次中间操作都会返回新的流,原有流对象不会被改变
  4. 流的操作分为两大类:中间操作终端操作
  • 中间操作:可以连续多个,作用是对数据做过滤、转换等处理,执行后仍返回流,支持链式编程;
  • 终端操作:只能有一个,必须放在所有操作的末尾,执行后流立即关闭,不再继续流转。

二、创建 Stream 流

日常开发中,主要从数组集合两类数据源创建流,下面分场景演示代码。

1. 从数组创建流

可以使用 Arrays.stream()Stream.of() 两种方式:

import java.util.Arrays;
import java.util.stream.Stream;

public class StreamDemo {
    public static void main(String[] args) {
        // 方式1:Arrays.stream() 创建流
        Integer[] arr = {1, 2, 3, 4, 5};
        Stream<Integer> stream1 = Arrays.stream(arr);

        // 方式2:Stream.of() 创建流
        Stream<Integer> stream2 = Stream.of(arr);
    }
}

2. 从集合创建流

Java 8 给 Collection 接口新增了 stream() 方法,所有集合都可直接调用;同时还支持创建并发流parallelStream(),底层默认使用 ForkJoinPool.commonPool() 线程池,适合大数据量并行处理。

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class StreamDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("MySQL");
        list.add("Linux");

        // 普通串行流
        Stream<String> stream = list.stream();
        // 并发流
        Stream<String> parallelStream = list.parallelStream();
    }
}

三、常用流操作

结合中间操作、终端操作,讲解开发中最常用的 API,并搭配完整示例。

1. 去重 distinct ()(中间操作)

distinct() 会去除流中重复元素,返回新流,常搭配终端操作 count()(统计元素个数)使用。

import java.util.ArrayList;
import java.util.List;

public class StreamDemo {
    public static void main(String[] args) {
        List<Integer> numList = new ArrayList<>();
        numList.add(1);
        numList.add(2);
        numList.add(2);
        numList.add(3);
        numList.add(3);

        // 去重 + 统计元素总数
        long count = numList.stream()
                .distinct() // 中间操作:去重
                .count();    // 终端操作:统计数量
        System.out.println("去重后元素个数:" + count); // 输出:3
    }
}

2. 过滤 filter ()(中间操作)

按照指定条件筛选元素,只保留符合条件的数据。

import java.util.ArrayList;
import java.util.List;

public class StreamDemo {
    public static void main(String[] args) {
        List<Integer> numList = List.of(1, 2, 3, 4, 5, 6);

        // 筛选大于3的元素并遍历输出
        numList.stream()
                .filter(n -> n > 3) // 过滤条件
                .forEach(System.out::println); // 终端操作:遍历
    }
}

3. 映射 map ()(中间操作)

将流中的元素转换为新类型 / 新数据,比如类型转换、字段提取、数据运算。

import java.util.List;

public class StreamDemo {
    public static void main(String[] args) {
        List<String> strList = List.of("1", "2", "3", "4");

        // 将字符串转为整数
        strList.stream()
                .map(Integer::parseInt) // 映射转换
                .forEach(System.out::println);
    }
}

4. 元素匹配(终端操作)

Stream 提供三种匹配方法,返回布尔值,属于终端操作:

  • anyMatch():任意一个元素满足条件,返回 true;
  • allMatch()所有元素都满足条件,才返回 true;
  • noneMatch()所有元素都不满足条件,才返回 true。
import java.util.List;

public class StreamDemo {
    public static void main(String[] args) {
        List<Integer> numList = List.of(2, 4, 6, 8);

        // 是否存在大于5的元素
        boolean any = numList.stream().anyMatch(n -> n > 5);
        // 是否全部是偶数
        boolean all = numList.stream().allMatch(n -> n % 2 == 0);
        // 是否没有大于10的元素
        boolean none = numList.stream().noneMatch(n -> n > 10);

        System.out.println(any);   // true
        System.out.println(all);   // true
        System.out.println(none);  // true
    }
}

5. 归约组合 reduce ()(终端操作)

reduce() 用于将流中所有元素迭代合并、计算,常用于求和、求乘积、取最值等场景。

import java.util.List;

public class StreamDemo {
    public static void main(String[] args) {
        List<Integer> numList = List.of(1, 2, 3, 4, 5);

        // 累加求和
        numList.stream()
                .reduce(Integer::sum)
                .ifPresent(sum -> System.out.println("总和:" + sum)); // 输出:15
    }
}

四、流转换为数组 / 集合

处理完流数据后,我们经常需要把流还原为数组或集合,主要使用 toArray()collect() 方法。

1. 流转数组 toArray ()

import java.util.List;

public class StreamDemo {
    public static void main(String[] args) {
        List<String> list = List.of("Java", "MySQL", "Linux");
        // 流转数组
        String[] array = list.stream().toArray(String[]::new);
        for (String s : array) {
            System.out.println(s);
        }
    }
}

2. 流转集合 collect ()

借助 Collectors 工具类,可以将流收集为 ListSet 等不同集合:

import java.util.List;
import java.util.stream.Collectors;

public class StreamDemo {
    public static void main(String[] args) {
        List<Integer> numList = List.of(1, 2, 3, 4, 5);

        // 过滤后重新收集为List集合
        List<Integer> newList = numList.stream()
                .filter(n -> n % 2 == 0)
                .collect(Collectors.toList());

        System.out.println(newList); // 输出 [2, 4]
    }
}

五、总结

Stream API 极大简化了集合与数组的处理逻辑,结合 Lambda 表达式后代码更加精简。使用时记住两个关键点:

  1. 中间操作延迟执行,必须配合终端操作才会触发整个流的执行;
  2. 流只能使用一次,终端操作执行完毕后流自动关闭,不可重复操作。

后续我会继续更新 Java 进阶相关内容,感兴趣的朋友可以持续关注,有问题欢迎在评论区交流~

Tags:

发表回复

Your email address will not be published. Required fields are marked *.

*
*