Java Stream

返回 面试 · 速查全集 Java常见面试题

Java 8 声明式数据处理管道:中间操作惰性求值,终止操作触发执行;不修改源集合。详解 StreamLambda与函数式编程


Stream 是什么

特点说明
不存数据元素来自集合/数组/生成器
不修改源产生新结果
惰性中间操作filter/map 链在 collect 等终止操作前不执行
可并行parallelStream() / parallel()

操作分类

source → 中间操作* → 终止操作(必须)
         filter/map/flatMap/sorted/distinct/limit
         collect/forEach/reduce/count/findFirst

一次 Stream 只能消费一次;终止后再用需重新 stream()


常用 API

类型示例
创建list.stream()Stream.of()IntStream.range(1,5)
过滤filterdistinctlimitskip
转换mapflatMapmapToInt
排序sorted()sorted(Comparator.comparing(...))
收集collect(toList())groupingBytoMapjoining
规约reducecountsum(数值流)
匹配anyMatchallMatchfindFirst
List<String> names = users.stream()
    .filter(u -> u.getAge() >= 18)
    .map(User::getName)
    .sorted()
    .collect(Collectors.toList());

map vs flatMap

mapflatMap
关系1 → 11 → 0..n,再展平
map(String::length)flatMap(s -> Arrays.stream(s.split(" ")))

collect 常考

// 分组
Map<String, List<User>> byDept =
    users.stream().collect(Collectors.groupingBy(User::getDept));
 
// toMap(注意 key 冲突)
Map<Long, User> map = users.stream()
    .collect(Collectors.toMap(User::getId, u -> u, (a, b) -> b));
 
// 字符串拼接
Collectors.joining(", ", "[", "]");

toMap 无 merge 函数时 key 重复抛 IllegalStateException


Stream vs 传统 for

forStream
风格命令式声明式
并行手动parallelStream
调试链长时难
性能小数据 often 更快大数据 + 并行有优势

简单遍历、需 break/continue 时 for 更直观;过滤-映射-聚合 用 Stream 更清晰。


并行流注意

  • 使用 ForkJoinPool.commonPool()
  • 数据量小时并行更慢(调度开销)
  • forEach 无序;有序用 forEachOrdered
  • 禁止在 pipeline 里改共享变量;用 collect 等线程安全归约

常见面试题

Q:Stream 和 Collection 区别?
A:Collection 是数据结构;Stream 是计算视图,一次性管道。

Q:中间操作为什么叫惰性?
A:只有遇到 collect/forEach 等终止操作才遍历;可短路(findFirst + filter)。

Q:peek 能改元素吗?
A:可以改对象内部字段(引用类型);不要依赖 peek 做业务逻辑,仅调试。

Q:reducecollect
A:reduce 归约为单个值(Optional);collect 用 Collector 转为 List/Map 等可变容器。

Q:IntStream 好处?
A:避免 Integer 装箱,提供 sum/average/summaryStatistics


相关笔记