当前位置: 代码网 > it编程>编程语言>Java > Java Stream所有方法实例详解

Java Stream所有方法实例详解

2025年12月27日 Java 我要评论
一、stream 创建方法方法说明示例stream()从集合创建顺序流list.stream()parallelstream()创建并行流list.parallelstream()stream.of(

一、stream 创建方法

方法说明示例
stream()从集合创建顺序流list.stream()
parallelstream()创建并行流list.parallelstream()
stream.of()由一组元素创建流stream.of(1, 2, 3)
arrays.stream()由数组创建流arrays.stream(arr)
stream.iterate()生成无限流stream.iterate(0, n -> n+2).limit(5)
stream.generate()生成无限流stream.generate(math::random).limit(5)

二、stream 中间操作(intermediate operations)

这些方法返回新的 stream,允许链式调用。

方法说明示例
filter(predicate)过滤元素stream.filter(x -> x > 5)
map(function)元素映射stream.map(x -> x * 2)
flatmap(function)展开嵌套流stream.flatmap(list -> list.stream())
distinct()去重stream.distinct()
sorted() / sorted(comparator)排序stream.sorted() / stream.sorted(comparator.reverseorder())
peek(consumer)元素遍历但不终止流stream.peek(system.out::println)
limit(long n)截取前 n 个元素stream.limit(3)
skip(long n)跳过前 n 个元素stream.skip(2)

三、stream 终止操作(terminal operations)

这些方法会产生结果或副作用,流被“消费”后不可再用。

方法说明示例
foreach(consumer)遍历元素stream.foreach(system.out::println)
collect(collector)收集结果stream.collect(collectors.tolist())
toarray()转数组stream.toarray()
reduce(binaryoperator)规约(聚合)stream.reduce((a, b) -> a + b)
count()计数stream.count()
anymatch(predicate)是否有任意元素匹配stream.anymatch(x -> x > 5)
allmatch(predicate)是否所有元素都匹配stream.allmatch(x -> x > 5)
nonematch(predicate)是否没有元素匹配stream.nonematch(x -> x > 5)
findfirst()查找第一个元素stream.findfirst()
findany()查找任意元素stream.findany()
min(comparator)最小值stream.min(comparator.naturalorder())
max(comparator)最大值stream.max(comparator.naturalorder())

四、常用 collector 收集器

方法说明示例
collectors.tolist()转 liststream.collect(collectors.tolist())
collectors.toset()转 setstream.collect(collectors.toset())
collectors.tomap()转 mapstream.collect(collectors.tomap(x -> x, x -> x*2))
collectors.joining()字符串拼接stream.collect(collectors.joining(","))
collectors.groupingby()分组stream.collect(collectors.groupingby(x -> x%2))
collectors.partitioningby()分区stream.collect(collectors.partitioningby(x -> x > 5))
collectors.counting()计数stream.collect(collectors.counting())
collectors.summingint()求和stream.collect(collectors.summingint(x -> x))
collectors.averagingint()平均值stream.collect(collectors.averagingint(x -> x))
collectors.maxby()最大值stream.collect(collectors.maxby(comparator.naturalorder()))
collectors.minby()最小值stream.collect(collectors.minby(comparator.naturalorder()))

五、示例代码

list<integer> list = arrays.aslist(1, 2, 3, 4, 5, 6);
// 过滤、映射、收集
list<integer> result = list.stream()
    .filter(x -> x > 3)
    .map(x -> x * 2)
    .collect(collectors.tolist()); // [8, 10, 12]
// 分组
map<boolean, list<integer>> partitioned = list.stream()
    .collect(collectors.partitioningby(x -> x % 2 == 0)); 
// 计数
long count = list.stream().filter(x -> x > 3).count();
// 求和
int sum = list.stream().reduce(0, integer::sum);

六、补充说明

  • 中间操作是惰性求值,只有终止操作执行时才会遍历数据。
  • stream 不能被复用,终止操作后需重新创建流。
  • 并行流(parallelstream)适用于大数据量,但需注意线程安全和性能。

七、stream 高级用法

1. 多级分组

map<string, map<integer, list<user>>> multigroup = users.stream()
    .collect(collectors.groupingby(
        user::getcity,
        collectors.groupingby(user::getage)
    ));

说明:先按城市分组,再按年龄分组,结果是嵌套的 map。

2. 分区与分组的区别

  • 分区:只有两组(true/false),适合布尔条件。
  • 分组:可以有多个分组键。
map<boolean, list<integer>> partition = list.stream()
    .collect(collectors.partitioningby(x -> x > 3));

3. 自定义收集器

可以通过collector.of自定义收集逻辑:

collector<integer, ?, set<integer>> tocustomset = collector.of(
    hashset::new,
    set::add,
    (left, right) -> { left.addall(right); return left; }
);
set<integer> set = list.stream().collect(tocustomset);

4. 并行流

list.parallelstream()
    .filter(x -> x > 3)
    .foreach(system.out::println);

注意:并行流适合 cpu 密集型任务,io 密集型需谨慎;操作需线程安全。

5. optional 结合 stream

optional<integer> first = list.stream().filter(x -> x > 3).findfirst();
first.ifpresent(system.out::println);

八、常见陷阱与注意点

  • 流只能用一次
    • 流操作后已关闭,不能再操作,否则抛异常。
  • 修改集合元素
    • 不建议在流操作中直接修改原集合元素,推荐返回新集合。
  • 空指针问题
    • stream 操作前应确保集合非 null,推荐使用 optional.ofnullable(list).orelse(collections.emptylist()).stream()
  • 性能问题
    • distinct()sorted()等操作会增加性能消耗。
    • 并行流适合数据量大且操作无副作用的场景。

九、部分方法源码简析

1. filter

default stream<t> filter(predicate<? super t> predicate) {
    objects.requirenonnull(predicate);
    return new referencepipeline.statelessop<>(this, streamshape.reference, streamopflag.not_sorted) {
        @override
        sink<t> opwrapsink(int flags, sink<t> sink) {
            return new sink.chainedreference<t, t>(sink) {
                @override
                public void accept(t t) {
                    if (predicate.test(t)) downstream.accept(t);
                }
            };
        }
    };
}

说明:filter 实际上是对每个元素执行 predicate 判断,符合条件则传递到下游。

2. map

default <r> stream<r> map(function<? super t, ? extends r> mapper) {
    objects.requirenonnull(mapper);
    return new referencepipeline.statelessop<>(this, streamshape.reference, streamopflag.not_sorted) {
        @override
        sink<t> opwrapsink(int flags, sink<r> sink) {
            return new sink.chainedreference<t, r>(sink) {
                @override
                public void accept(t t) {
                    downstream.accept(mapper.apply(t));
                }
            };
        }
    };
}

说明:map 通过 function 映射每个元素,返回新的流。

十、典型业务场景举例

1. 数据去重并排序

list<string> sorted = list.stream()
    .distinct()
    .sorted()
    .collect(collectors.tolist());

2. 统计分组后的最大值

map<string, optional<user>> maxagebycity = users.stream()
    .collect(collectors.groupingby(
        user::getcity,
        collectors.maxby(comparator.comparingint(user::getage))
    ));

3. 多字段分组统计

map<string, map<integer, long>> groupcount = users.stream()
    .collect(collectors.groupingby(
        user::getcity,
        collectors.groupingby(user::getage, collectors.counting())
    ));

4. 批量字段提取

list<string> names = users.stream()
    .map(user::getname)
    .collect(collectors.tolist());

5. stream 处理 map

map<string, integer> map = ...;
list<string> keys = map.entryset().stream()
    .filter(e -> e.getvalue() > 5)
    .map(map.entry::getkey)
    .collect(collectors.tolist());

十一、stream api 性能建议

  • 尽量减少中间操作链长度,必要时合并操作。
  • 大数据量推荐并行流,但需测试线程安全和实际效率。
  • 优先使用基本类型流(intstream、longstream、doublestream)可减少装箱/拆箱开销。
  • 避免在流中写复杂逻辑,建议拆分为多个方法提高可读性。

十二、stream 相关扩展

  • intstream/longstream/doublestream:针对基本类型的流,效率更高。
  • collectors.toconcurrentmap:并发收集器,适合并行流。
  • collectors.mapping:在分组或分区时对元素做映射。
  • collectors.reducing:自定义规约操作。

十三、基本类型流详解

java 提供了三种基本类型流,分别是 intstreamlongstream 和 doublestream,它们避免了自动装箱/拆箱,提高了性能。

创建方式

intstream intstream = intstream.of(1, 2, 3, 4);
longstream longstream = longstream.range(1, 10); // [1,9]
doublestream doublestream = doublestream.generate(math::random).limit(5);

常用方法

方法说明示例
sum()求和intstream.sum()
average()平均值intstream.average().getasdouble()
max() / min()最大/最小值intstream.max().getasint()
boxed()转换为对象流intstream.boxed()
maptoobj()基本类型流转对象流intstream.maptoobj(string::valueof)

十四、流的收集与转换技巧

1. 转换为 map,处理 key 重复

// value 相加
map<string, integer> map = list.stream()
    .collect(collectors.tomap(
        user::getname,
        user::getscore,
        integer::sum // 合并函数
    ));

2. 收集为不可变集合

list<string> unmodifiablelist = list.stream()
    .collect(collectors.collectingandthen(
        collectors.tolist(),
        collections::unmodifiablelist
    ));

3. 多字段分组

map<string, map<integer, list<user>>> group = users.stream()
    .collect(collectors.groupingby(
        user::getcity,
        collectors.groupingby(user::getage)
    ));

十五、stream 与并发/线程安全

  • 并行流parallelstream() 会自动分片并行处理,适合无状态、无副作用的操作。
  • 线程安全收集:使用 collectors.toconcurrentmapconcurrenthashmap 等。
concurrentmap<string, integer> concurrentmap = list.parallelstream()
    .collect(collectors.toconcurrentmap(user::getname, user::getscore));

十六、stream 排序技巧

1. 单字段排序

list.stream()
    .sorted(comparator.comparing(user::getage))
    .collect(collectors.tolist());

2. 多字段排序

list.stream()
    .sorted(comparator.comparing(user::getage)
        .thencomparing(user::getname))
    .collect(collectors.tolist());

3. 逆序排序

list.stream()
    .sorted(comparator.comparing(user::getage).reversed())
    .collect(collectors.tolist());

十七、stream 实用代码片段

1. 找出重复元素

set<integer> seen = new hashset<>();
set<integer> duplicates = list.stream()
    .filter(n -> !seen.add(n))
    .collect(collectors.toset());

2. 分页功能

int page = 2, size = 5;
list<integer> pagelist = list.stream()
    .skip((page - 1) * size)
    .limit(size)
    .collect(collectors.tolist());

3. 按条件统计数量

long count = list.stream().filter(x -> x > 10).count();

4. 合并两个 list 并去重

list<integer> merged = stream.concat(list1.stream(), list2.stream())
    .distinct()
    .collect(collectors.tolist());

十八、常见问题与解决方案

1. stream 只用一次

stream<string> s = list.stream();
s.foreach(system.out::println);
// s.foreach(...) // 抛异常,不可再用

解决:重新创建流。

2. nullpointerexception

集合为 null 时不能直接调用 stream()

list<string> safelist = optional.ofnullable(list)
    .orelse(collections.emptylist());
safelist.stream()...

3. 性能瓶颈

  • 避免在流操作中写复杂逻辑,拆分方法。
  • 并行流适合数据量大且操作无副作用,需实际测试。

十九、collectors 的扩展用法

1. mapping

分组后对分组内元素做映射:

map<string, list<string>> namegroup = users.stream()
    .collect(collectors.groupingby(
        user::getcity,
        collectors.mapping(user::getname, collectors.tolist())
    ));

2. reducing

自定义聚合:

int totalscore = users.stream()
    .collect(collectors.reducing(0, user::getscore, integer::sum));

二十、stream 处理嵌套集合

list<list<integer>> nested = arrays.aslist(
    arrays.aslist(1,2),
    arrays.aslist(3,4)
);
list<integer> flat = nested.stream()
    .flatmap(collection::stream)
    .collect(collectors.tolist());

二十一、stream api 新增方法(java 9+)

如果你用的是 java 9 及以上,还可以用:

  • takewhile(predicate):从头开始,遇到不满足条件就停止。
  • dropwhile(predicate):从头开始,遇到不满足条件后开始收集。
  • stream.ofnullable(obj):对象为 null 返回空流,否则返回单元素流。
stream.ofnullable(null).count(); // 0
stream.ofnullable("abc").count(); // 1

二十二、stream 与 lambda 表达式最佳实践

  • 保持流操作简洁,避免嵌套 lambda 过多。
  • 推荐将复杂逻辑提取为方法引用或单独方法。
  • 用注释说明复杂的流链。

总结

java stream 提供了丰富的 api,适合处理集合的各种操作,包括过滤、映射、分组、聚合、排序、去重等。掌握 stream 可以极大提升 java 代码的简洁性和表现力。

到此这篇关于java stream所有方法实例详解的文章就介绍到这了,更多相关java stream所有方法内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com