拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

如果像 AI 一样写 Lambda(第 4 篇):聚合与收集

如果像 AI 一样写 Lambda(第 4 篇):聚合与收集

如果像 AI 一样写 Lambda(第 4 篇):聚合与收集(Stream 应用篇)

一句话总结:流处理完总要"收摊"。Collectors.toList/joining/groupingBy/reduce是把流变回集合、字符串、Map、单值的四大收摊工具,它们本身就是::的重度用户。

相关文档:《如果像AI一样写Lambda-第3篇-转换与过滤-通俗版.md》——先加工,再收摊。

0. 比喻:收银台汇总

写法比喻
普通人的写法一个个手记,最后自己算总账
函数式写法把"汇总规则"告诉收银机
AI lambda 简写规则直接指到现成方法,比如"求和"用Integer::sum表达

1. 流变 List:collect(toList)

场景:加工完的流,装回一个 List。

① 普通人的写法:for 循环逐个装

List<String>result=newArrayList<>();for(Stringname:names){if(name!=null){result.add(name.trim());}}

② 函数式写法:filter + map + collect

List<String>result=names.stream().filter(name->name!=null).map(name->name.trim()).collect(Collectors.toList());

③ AI lambda 简写:全链路方法引用

List<String>result=names.stream().filter(Objects::nonNull).map(String::trim).collect(Collectors.toList());

Collectors.toList()是固定搭配,AI 几乎不会去 new ArrayList 手抄。filter → map → collect三段式的组合正是第 3 篇两个 API 的串联。

2. 流变字符串:joining

场景:把列表拼成逗号分隔的字符串。

① 普通人的写法:StringBuilder 手拼

List<String>items=Arrays.asList("A","B","C");StringBuildersb=newStringBuilder();for(inti=0;i<items.size();i++){if(i>0){sb.append(",");}sb.append(items.get(i));}Stringresult=sb.toString();// "A,B,C"

② 函数式写法:collect(joining)

Stringresult=items.stream().collect(Collectors.joining(","));

③ AI lambda 简写:先流式加工再拼接

Stringresult=names.stream().filter(Objects::nonNull).map(String::trim).collect(Collectors.joining(","));

补充:如果只是纯列表拼接(不加工),String.join(",", items)比 stream 更短;joining的舞台在"先过滤、再转换、最后拼"的组合拳里。

3. 流变 Map:groupingBy

场景:按某个规则把列表分组,变成 Map。

① 普通人的写法:for 循环 + computeIfAbsent

Map<String,List<String>>groupMap=newHashMap<>();for(Stringname:names){Stringkey=name.substring(0,2);// 按前两个字符分组groupMap.computeIfAbsent(key,k->newArrayList<>()).add(name);}

② 函数式写法:groupingBy + lambda

Map<String,List<String>>groupMap=names.stream().collect(Collectors.groupingBy(name->name.substring(0,2)));

③ AI lambda 简写:分组 + 计数一步到位

Map<String,Long>counts=names.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));

groupingBy的第二个参数可以继续嵌套收集器,统计、再映射都能一行完成,这是它被 AI 偏爱的原因。

4. 流变单值:reduce

场景:把一堆数合成一个结果(求和、求最大值)。

① 普通人的写法:for 循环累加

List<Integer>nums=Arrays.asList(1,2,3,4,5);intsum=0;for(intn:nums){sum+=n;}

② 函数式写法:reduce + 完整 lambda

intsum=nums.stream().reduce(0,(a,b)->a+b);

③ AI lambda 简写:多参数方法引用

intsum=nums.stream().reduce(0,Integer::sum);

Integer::sum等价于(a, b) -> Integer.sum(a, b)——方法引用同样支持多参数,只要参数个数对得上。求最大值同理:reduce(Integer::max)。

5. 四大收摊工具对照表

工具目标形态典型用途一句话记忆
Collectors.toList()List过滤/转换后落盘流 → 列表
Collectors.joining(",")String拼接展示流 → 字符串
Collectors.groupingBy(...)Map分组统计流 → 分组
reduce(0, Integer::sum)单值求和/求极值流 → 单值

6. 陷阱:Collectors.toMap 重复 key 会炸

groupingBy自动处理重复 key(合并成 List),但toMap不会:

// ❌ 两个元素算出的 key 相同 → 抛 IllegalStateExceptionMap<String,String>map=names.stream().collect(Collectors.toMap(name->name.substring(0,2),Function.identity()));// ✅ 必须给出冲突策略(k1, k2) -> k2 表示后到的覆盖先到的Map<String,String>map=names.stream().collect(Collectors.toMap(name->name.substring(0,2),Function.identity(),(k1,k2)->k2));

不确定 key 是否唯一时,groupingBy永远比toMap安全。

一页速记

  • 收摊四件套:流变 List 用toList,变字符串用joining,变 Map 用groupingBy,变单值用reduce
  • filter → map → collect是 AI 处理列表的标准三段式
  • 纯列表拼接用String.join(",", items),流式加工后才用joining
  • reduce(0, Integer::sum)= 求和,reduce(Integer::max)= 求最大值
  • 方法引用支持多参数:(a, b) -> a + b=Integer::sum
  • toMap遇重复 key 会抛异常,必须写第三参(k1, k2) -> k2;不确定唯一就用groupingBy
返回列表