Java 8如何通过Stream正确生成按fileName分组的Map<String, List<ExampleClass>>
问题原因排查与解决
你编写的分组代码本身逻辑没有错误,只是存在冗余:Collectors.groupingBy的默认下游收集器就是将同组元素归集为List,可以简化为如下写法,和原有代码效果完全一致:
Map<String, List<ExampleClass>> mapValues = items .stream() .collect(Collectors.groupingBy(ExampleClass::getFileName));
异常结果的常见排查方向
你遇到的所有对象都出现在每个fileName对应列表中的问题,基本都是代码实现细节错误导致的,按以下步骤排查即可解决:
1. 检查
ExampleClass的getFileNamegetter方法实现
大部分这类问题都是getter编写错误导致的,确认你的getter是返回当前实例的fileName字段,而不是返回静态变量、其他字段、或者固定值:
// 正确的getter实现示例 public String getFileName() { return this.fileName; }
如果所有实例的getFileName返回值都相同(比如全部返回null、或者同一个固定字符串),那么所有元素都会被分到同一个key的列表中,看起来就像是所有对象都出现在了列表里。
2. 确认原始数据符合预期
打印所有待分组的ExampleClass实例的fileName值,确认确实存在不同的fileName:
items.forEach(item -> System.out.println("实例fileName:" + item.getFileName()));
如果输出的所有值都一致,说明你填充ExampleClass字段的逻辑有问题,和分组代码无关。
3. 检查结果验证逻辑是否正确
很多时候分组本身是正确的,是打印/使用结果的时候写错了逻辑,比如遍历map的时候错误打印了全量的items列表,而不是当前key对应的value。可以用以下代码验证分组结果:
mapValues.forEach((key, valueList) -> { System.out.printf("分组key:%s,对应列表大小:%d%n", key, valueList.size()); // 打印列表中每个元素的fileName,确认和key一致 valueList.forEach(example -> System.out.printf(" 元素fileName:%s%n", example.getFileName())); });
4. 排查并发修改问题
如果你的items列表在流处理过程中被其他线程修改,或者ExampleClass的fileName字段被并发修改,也可能导致分组计算异常,需要确保流处理期间数据源没有被并发修改。
内容的提问来源于stack exchange,提问作者Nahuel Giani
相关产品推荐
相关产品推荐

