You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Java Stream API读取文件首尾行并生成指定Map

使用Java Stream API单次流水线获取文件首末行并生成Map

你的文本文件内容如下:

Column_A Column_B

Cell_1 Cell_2

Cell_3 Cell_4

需求是在单个Stream流水线中获取有效首行和末行,最终生成如下格式的Map:

{ "Column_A": "Cell_3", "Column_B": "Cell_4" }

需要注意:你原先两次调用br.lines()的写法存在问题——BufferedReader对应的Stream只能被消费一次,第二次调用会直接抛出IllegalStateException。下面提供两种单流水线的可行方案:

方案一:自定义收集器(支持并行流)

先定义一个容器类存储首行和末行,再实现对应的收集器:

// 用于存储首行和末行的容器类
class LinePair {
    private final String first;
    private String last;

    private LinePair(String first) {
        this.first = first;
        this.last = first;
    }

    public void updateLast(String line) {
        this.last = line;
    }

    public String getFirst() {
        return first;
    }

    public String getLast() {
        return last;
    }

    // 自定义收集器:收集有效行的首行和末行
    public static Collector<String, ?, LinePair> toLinePair() {
        return Collector.of(
            () -> null,
            (pair, line) -> {
                if (pair == null) {
                    return line.isBlank() ? null : new LinePair(line);
                } else {
                    if (!line.isBlank()) {
                        pair.updateLast(line);
                    }
                    return pair;
                }
            },
            (pair1, pair2) -> {
                if (pair1 == null) return pair2;
                if (pair2 == null) return pair1;
                pair1.updateLast(pair2.getLast());
                return pair1;
            },
            Collector.Characteristics.UNORDERED
        );
    }
}

使用收集器完成处理:

try (BufferedReader br = new BufferedReader(new FileReader("your-file.txt"))) {
    LinePair linePair = br.lines()
                          .filter(line -> !line.isBlank())
                          .collect(LinePair.toLinePair());

    if (linePair != null) {
        String[] keys = linePair.getFirst().split("\\s+"); // 适配多空格分隔
        String[] values = linePair.getLast().split("\\s+");

        Map<String, String> result = IntStream.range(0, keys.length)
                                              .boxed()
                                              .collect(Collectors.toMap(
                                                  i -> keys[i],
                                                  i -> values[i],
                                                  (oldVal, newVal) -> oldVal,
                                                  HashMap::new
                                              ));
        System.out.println(result);
    }
} catch (IOException e) {
    e.printStackTrace();
}

方案二:AtomicReference记录首行(简洁高效,适合顺序流)

利用peek操作在遍历过程中记录首行,同时用reduce获取末行,全程单流水线:

try (BufferedReader br = new BufferedReader(new FileReader("your-file.txt"))) {
    AtomicReference<String> firstLine = new AtomicReference<>();
    String lastLine = br.lines()
                        .filter(line -> !line.isBlank())
                        .peek(line -> firstLine.compareAndSet(null, line)) // 仅首次设置首行
                        .reduce((a, b) -> b)
                        .orElseThrow(() -> new IllegalStateException("文件无有效内容"));

    String[] keys = firstLine.get().split("\\s+");
    String[] values = lastLine.split("\\s+");

    Map<String, String> result = IntStream.range(0, Math.min(keys.length, values.length))
                                          .boxed()
                                          .collect(Collectors.toMap(
                                              i -> keys[i],
                                              i -> values[i],
                                              (o, n) -> o,
                                              HashMap::new
                                          ));
    System.out.println(result);
} catch (IOException e) {
    e.printStackTrace();
}

关键说明

  1. 两个方案都只遍历文件一次,避免了Stream重复消费的问题
  2. 使用\\s+分割字符串,适配列之间多个空格的场景
  3. 过滤空行,确保首末行都是有效数据行
  4. 方案二更适合普通的顺序文件流,代码更简洁;方案一支持并行流场景

内容的提问来源于stack exchange,提问作者Alexey Dunaitsev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 14:23:11