如何用Java 8 Stream按条件将流数据分类存入不同列表
Java 8 Stream 按指定字段分类数据的优化方案
需求场景
现有分号分隔的数据流,需要基于索引为2的字段(如L100、L120等),使用Java 8 Stream将数据分类存入对应标识的不同列表中。
原始数据流
452857;0;L100;csO;20220411;20220411;EUR;000101435;+; ;F;1;EUR;000100000;+; 452857;0;L120;csO;20220411;20220411;EUR;000101435;+; ;F;1;EUR;000100000;+; 452857;0;L121;csO;20220411;20220411;EUR;000101435;+; ;F;1;EUR;000100000;+; 452857;0;L126;csO;20220411;20220411;EUR;000101435;+; ;F;1;EUR;000100000;+; 452857;0;L100;csO;20220411;20220411;EUR;000101435;+; ;F;1;EUR;000100000;+; 452857;0;L122;csO;20220411;20220411;EUR;000101435;+; ;F;1;EUR;000100000;+;
用户原始实现
用户已尝试以下代码,但希望更简洁高效的写法:
List<String> L100_ENTITY_NAMES = Arrays.asList("L100", "L120", "L121", "L122", "L126"); List<List<String>> list= L100_ENTITY_NAMES.stream() .map(entity -> Arrays.stream(splittedLine) .filter(line -> { String[] values = line.split(String.valueOf(DELIMITER)); if(values.length > 0){ return entity.equals(values[2]); } else{ return false; } }).collect(Collectors.toList())).collect(Collectors.toList());
优化建议
1. 用Collectors.groupingBy一次性分组,减少遍历次数
原始代码会遍历数据源多次(每个实体标识对应一次遍历),效率较低。改用groupingBy只需遍历一次即可完成分组,性能大幅提升:
// 第一步:按索引2的字段分组,得到标识与对应行的映射 Map<String, List<String>> groupedMap = Arrays.stream(splittedLine) .collect(Collectors.groupingBy(line -> { String[] values = line.split(String.valueOf(DELIMITER)); // 避免数组越界,处理分割后长度不足3的异常情况 return values.length >= 3 ? values[2] : "UNKNOWN"; })); // 第二步:按指定顺序提取目标标识对应的列表 List<List<String>> resultList = L100_ENTITY_NAMES.stream() .map(groupedMap::get) // 处理标识不存在的情况,返回空列表而非null .map(list -> list == null ? Collections.emptyList() : list) .collect(Collectors.toList());
2. 提取分割逻辑为独立方法,提升可读性
把分割字符串并获取标识的逻辑抽成单独方法,让Stream代码更简洁清晰:
private static String getEntityId(String line, char delimiter) { String[] values = line.split(String.valueOf(delimiter)); return values.length >= 3 ? values[2] : "UNKNOWN"; } // 使用简化后的分组逻辑 Map<String, List<String>> groupedMap = Arrays.stream(splittedLine) .collect(Collectors.groupingBy(line -> getEntityId(line, DELIMITER)));
3. 避免重复分割字符串
原始代码中每行数据会被多次分割(每个实体标识遍历一次就分割一次),优化后每行仅分割一次,减少不必要的计算开销。
4. 修复数组越界风险
原始代码仅判断values.length > 0,但访问values[2]需要数组长度至少为3,否则会抛出ArrayIndexOutOfBoundsException。优化后的代码增加了长度判断,有效避免异常。
内容的提问来源于stack exchange,提问作者Pawan.Java
相关产品推荐
相关产品推荐

