用map()提取单个属性可替代冗长for循环,一行完成转换;flatMap适用于提取多个属性或处理嵌套结构;groupingBy结合filter可精准查重。

提取单个属性:用 map() 替代循环
遍历对象列表并提取某字段(如 name、id)生成新集合,是高频场景。传统 for 循环需手动创建 ArrayList、逐个 add,易错且冗长。
Stream API 一行即可完成:
-
.stream()将 List 转为流; -
.map(Person::getName)或.map(p -> p.getName())执行一对一映射(注意私有字段必须用 getter); -
.collect(Collectors.toList())收集结果,推荐toUnmodifiableList()(Java 10+)提升安全性。
⚠️ 若源集合可能为 null,务必前置判空;若对象本身可能为 null,加 .filter(Objects::nonNull) 防空指针。
提取多个属性:flatMap 拆解组合值
当一个对象含多个目标字段(如 bank.getOssIdCn() 和 bank.getOssIdEn()),需合并去重时,不能只用 map——它是一对一的。
立即学习“Java免费学习笔记(深入)”;
正确做法是 flatMap:
-
.flatMap(bank -> Stream.of(bank.getOssIdCn(), bank.getOssIdEn()))把每个对象“展开”为两个元素的子流; - 后续接
.filter(Objects::nonNull).distinct()清洗数据; - 最后
.collect(Collectors.toList())汇总。
这种写法避免了嵌套循环和中间 List,内存更友好,逻辑也更贴近“我要所有有效 ID”这一语义。
嵌套结构取值:层层 map + flatMap 链式穿透
面对多层嵌套(如 Employee → Department → List<address> → String city</address>),直接链式调用会触发空指针或 NPE。
安全提取唯一城市名示例:
-
.flatMap(emp -> emp.getDepartment().getAddresses().stream())先展平地址列表; -
.map(Address::getCity)提取城市; -
.filter(Objects::nonNull).distinct()去空、去重; - 全程保持无状态、不可变,适合并行流加速(
parallelStream())。
按属性查重:groupingBy + filter 精准定位重复实例
不依赖 equals/hashCode,仅根据某个字段(如 osName)找所有重复对象,适用未重写基础方法的类。
-
.collect(Collectors.groupingBy(Computer::getOsName))按字段分组,返回 Map<String, List<Computer>>; -
.entrySet().stream().filter(e -> e.getValue().size() > 1)筛出含多个元素的组; -
.flatMap(e -> e.getValue().stream())扁平化为原始对象流; - 若需保持原始顺序,改用
Collectors.groupingBy(..., LinkedHashMap::new, ...)。
该方案不构造全量中间 Map 再遍历,而是流式筛选,兼顾可读性与性能。


















