详解Stream流特性与常用操作

本文为个人总结,如有错误请评论区指出

文章目录

什么是Stream流

Stream 是Java 8 引入的对集合数据进行"流水线式"处理的工具

Stream流的四个特性

无存储性

Stream不保存数据,数据始终存储在原始数据源(集合、数组)中,Stream只负责处理

不变性

Stream操作不会修改原始数据源 ,所有的中间操作都会返回新的Stream,保证原数据不变

惰性执行

中间操作 (如:filter、map、sorted仅记录处理逻辑 ,不立即执行;只有调用终止操作 (如collect、forEach、count)时,才会触发整个流的执行

  • 中间操作:调用后不会立即执行,只是记录操作逻辑,返回新的Stream
  • 终止操作:只有调用终止操作时,所有中间才会一次性执行,执行完后Stream就会失效

一次性

Stream流是单向的、不可复用的 ,一旦执行了终止操作 ,这个Stream就会被消费掉,无法再次使用;如果需要重新操作数据,必须从数据源重新创建Stream

Stream常用操作

创建操作

  1. 从集合创建(stream () /parallelStream ()
  • stream():从 Collection 集合(List/Set/Map.values () 等)创建串行流,单线程按顺序处理元素;
  • parallelStream():创建并行流,多线程分发处理元素,顺序不可控,但大数据量下效率更高
java 复制代码
//从集合创建
List<String> list = Arrays.asList("wz","xg");
list.stream().forEach(System.out::print); // 输出: wzxg
list.parallelStream().forEach(System.out::print); // 输出:xgwz(并行流顺序可能乱)
  1. 从数组创建(Arrays.stream ()
  • 专门处理数组的流创建方法,会拆分数组元素生成流,而非将数组作为单个元素
  • 处理基本类型数组时,优先使用 Arrays.stream(),避免 Stream.of() 导致的 Stream<int[]> 类型问题;
  • 数组为 null 时会抛出NullPointerException需提前判空。
java 复制代码
//从数组创建
String[] arr = {"wz","xg"};
Arrays.stream(arr).forEach(System.out::print); // 输出: wzxg
  1. 直接生成(Stream.of ()
  • 允许传入 null 元素,但易引发后续空指针异常
  • 处理基本类型数组时(如 int[] arr = {1,2}),Stream.of(arr) 会生成 Stream<int[]>(数组作为单个元素),而非拆分元素。
java 复制代码
//直接生成
Stream.of("wzxg",666).forEach(System.out::print); // 输出: wzxg666
  1. 生成无限流(Stream.generate () / Stream.iterate ()
    方法定义:
java 复制代码
// 生成无限流:基于 Supplier 生成无规律元素
static <T> Stream<T> generate(Supplier<T> s)

// 生成无限流:基于初始值+迭代器生成有规律元素
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)

// Java 9+ 重载:支持终止条件
static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)
  • generate():通过 Supplier 函数无规律生成无限元素 (如随机数),需配合 limit() 截断;
  • iterate():基于初始值(seed) 和迭代函数(UnaryOperator) 生成有规律的无限元素 (如自增序列),Java 9+ 可指定终止条件。
java 复制代码
//生成无限流(需limit截断)
Stream.generate(Math::random).limit(2).forEach(n->System.out.printf("%.1f ",n)); // 输出: 0.1 0.2(随机值)
Stream.iterate(0, n->n+1).limit(2).forEach(System.out::print); // 输出:01

中间操作

  1. filter:过滤元素
    方法定义:
java 复制代码
Stream<T> filter(Predicate<? super T> predicate)

接收一个判断条件(Predicate 函数式接口),保留流中满足条件的元素,过滤掉不满足条件的元素,返回新的 Stream。

java 复制代码
Stream.of(1,2,3).filter(n->n%2==0).forEach(System.out::print); // 输出: 2
  1. map:转换元素(一对一)
    方法定义:
java 复制代码
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
  • T:原Stream中的元素类型
  • R:转换后新Stream中元素的类型
  • mapper:一个函数式接口,接收一个T类型元素,返回一个R类型结果,这个函数就是定义的转换规则
java 复制代码
Stream.of("a","b").map(String::toUpperCase).forEach(System.out::print); // 输出: AB
  1. flatMap:扁平化流(一对多)
    方法定义:
java 复制代码
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)

接收一个 "生成流" 的函数,将流中每个元素转换为一个新的子流,再将所有子流 "扁平化" 合并为一个整体流

java 复制代码
Stream.of(new String[]{"a","b"}, new String[]{"c"})
	.flatMap(Arrays::stream)// 每个数组转成子流,再合并
	.forEach(System.out::print); // 输出: abc
  1. distinct:去重
java 复制代码
Stream.of("a","a","b")
	.distinct()//去重
	.forEach(System.out::print); // 输出: ab
  1. sorted:排序
    方法定义:
java 复制代码
// 自然排序
Stream<T> sorted()

// 自定义排序(指定 Comparator)
Stream<T> sorted(Comparator<? super T> comparator)
  • 无参sorted():按元素的自然顺序排序(如数字升序、字符串字典序)
  • 有参sorted(Comparator):按自定义规则排序,无需元素实现 Comparable。
java 复制代码
Stream.of(3,1,2)
	.sorted()
	.forEach(System.out::print); // 输出: 123
  1. limit:保留前 N 个元素
java 复制代码
Stream.of(1,2,3)
	.limit(2)
	.forEach(System.out::print); // 输出: 12
  1. skip:跳过前 N 个元素
java 复制代码
Stream.of(1,2,3)
	.skip(1)
	.forEach(System.out::print); // 输出: 23
  1. peek:调试消费元素
java 复制代码
Stream.of(1,2)
	.peek(System.out::print)
	.count(); // 输出: 12

终止操作

  1. forEach:遍历元素
java 复制代码
Stream.of("a","b").forEach(System.out::print); // 输出: ab
  1. collect:收集结果(转换集合 / 数组)
    方法定义:
java 复制代码
<R, A> R collect(Collector<? super T, A, R> collector)
  • 接收Collector,将流中元素聚合为指定类型的结果(如 List、Set、Map)
  • Collectors提供了丰富的收集器(toList()/toSet()/groupingBy() 等);
  • 自定义收集器需实现Collector接口,适合复杂聚合场景。
java 复制代码
List<String> list = Stream.of("a").collect(Collectors.toList()); // list = ["a"]
  1. toArray:转数组
java 复制代码
String[] arr = Stream.of("a").toArray(String[]::new); // arr = ["a"]
  1. count:统计元素个数
    返回流中元素的总个数,返回值为 long 类型(避免 int 溢出)
java 复制代码
long num = Stream.of(1,2,3).count(); // num = 3
  1. max:找最大值
java 复制代码
int max = Stream.of(1,2).max(Integer::compare).get(); // max = 2
  1. min:找最小值
java 复制代码
int min = Stream.of(1,2).min(Integer::compare).get(); // min = 1
  1. findFirst:找第一个元素
java 复制代码
int first = Stream.of(1,2).findFirst().get(); // first = 1
  1. findAny:找任意元素
java 复制代码
int any = Stream.of(1,2,3).findAny().get(); // any = 1(串行流通常返回第一个)
  1. anyMatch:是否存在符合条件元素
java 复制代码
boolean b1 = Stream.of(1,2).anyMatch(n-> n>1); // b1 = true 2大于1
  1. allMatch:所有元素是否符合条件
java 复制代码
boolean b2 = Stream.of(2,4).allMatch(n->n%2==0); // b2 = true 2,4都可以被2整除
  1. noneMatch:是否无符合条件元素
java 复制代码
boolean b3 = Stream.of(1,3).noneMatch(n->n%2==0); // b3 = true 1,3都不能被2整除
  1. reduce:归约(聚合为单个值)
java 复制代码
int sum = Stream.of(1,2).reduce(0, Integer::sum); // sum = 3 1+2=3
相关推荐
H Corey2 小时前
Java抽象类与接口实战指南
java·开发语言·学习·intellij-idea
昊坤说不出的梦2 小时前
互联网大厂Java面试实录:核心技术栈深度解析与业务场景落地
java·大数据·spring boot·微服务·ai·技术栈·互联网面试
mr_orange_klj2 小时前
关于K8s身份权限的AI问答(豆包)
java·容器·kubernetes
徐先生 @_@|||2 小时前
JetBrains 公司的产品策略和技术架构(IDEA(Java)和Pycharm(Python)的编辑器)
java·python·架构
鱼跃鹰飞2 小时前
面试题:说一下Spring的事务传播特性
java·数据库·spring
Cliven_2 小时前
Github自动打包推送Maven中央仓库
java·github·maven
indexsunny2 小时前
互联网大厂Java求职面试实战:Spring Boot微服务与Kafka消息队列解析
java·spring boot·微服务·面试·kafka·jpa
invicinble2 小时前
关于spring的全量认识
java·spring
齐 飞2 小时前
JDK8中stream中常用方法
java