使用Stream处理CSV生成双Map时第二个Map为空的问题求助
问题分析与解决方案:Stream被消费导致secondMap为空
嘿,你的问题根源其实很典型——同一个InputStream只能被读取一次!
你创建的streamSupplier每次调用get(),都是基于同一个somefile InputStream生成新的Stream。但当你第一次用它填充firstMap时,这个InputStream已经被完全读取,指针走到了文件末尾。第二次再调用streamSupplier.get()时,BufferedReader根本读不到任何内容,所以secondMap自然是空的。
下面给你两种可行的解决思路:
方案1:先把所有行加载到内存,再分两次处理
适合文件体积不大的场景,简单直观:
public static void main(String[] args) throws FileNotFoundException { InputStream somefile = new FileInputStream("d:\\dummyfile.csv"); // 先把所有行读取到List中,避免重复消费InputStream List<String> lines = new BufferedReader(new InputStreamReader(somefile, StandardCharsets.ISO_8859_1)) .lines() .collect(Collectors.toList()); // 构建firstMap:将所有g[2]的值用逗号拼接,对应newVal1 Map<String, String> firstMap = lines.stream() .map(p -> p.split("\t")) // 注意:如果CSV中s[1]并非统一为"newVal1",请替换成固定key"newVal1" .collect(Collectors.groupingBy(s -> "newVal1", Collectors.mapping(g -> g[2], Collectors.joining(",")))); // 构建secondMap:s[0]作为key,s[2]作为value Map<String, String> secondMap = lines.stream() .map(p -> p.split("\t")) .collect(Collectors.toMap(s -> s[0], s -> s[2])); // 合并两个Map firstMap.putAll(secondMap); }
方案2:一次遍历同时构建结果Map(更高效)
如果你的CSV文件很大,不想占用太多内存,可以只读取一次文件,直接构建最终需要的Map:
public static void main(String[] args) throws FileNotFoundException { InputStream somefile = new FileInputStream("d:\\dummyfile.csv"); Map<String, String> resultMap = new HashMap<>(); StringBuilder aggregatedValues = new StringBuilder(); new BufferedReader(new InputStreamReader(somefile, StandardCharsets.ISO_8859_1)) .lines() .map(p -> p.split("\t")) // 加个过滤避免数组越界:行的列数不足3则跳过 .filter(arr -> arr.length >= 3) .forEach(arr -> { // 填充oldVal系列的键值对 resultMap.put(arr[0], arr[2]); // 收集所有s[2]的值,用于拼接newVal1的value if (aggregatedValues.length() > 0) { aggregatedValues.append(","); } aggregatedValues.append(arr[2]); }); // 添加newVal1的键值对 resultMap.put("newVal1", aggregatedValues.toString()); }
额外注意点:
- 你原代码中的
groupingBy(s -> s[1]),如果CSV里s[1]不是统一的newVal1,需要调整成固定key,否则会生成多个分组,和你的期望输出不符。 - 调用
split("\t")时,如果某一行的列数不足3,会抛出ArrayIndexOutOfBoundsException,建议像方案2那样加个filter做判断。
内容的提问来源于stack exchange,提问作者Elrich Queens
相关产品推荐
相关产品推荐

