用lambda表达式java实现计数变量

Mea*_*lay 4 java lambda java-8 java-stream

我有一个关于lambda表达式的问题.我有一个类Pair,它应该包含一个String和一个int.

Pair从文件中获取String.并且int表示行号.到目前为止我有这个:

 Stream<String> lineNumbers = Files.lines(Paths.get(fileName));
    List<Integer> posStream = Stream.iterate(0, x -> x + 1).limit(lineNumbers.count()).collect(Collectors.toList());
    lineNumbers.close();
    Stream<String> line = Files.lines(Paths.get(fileName));
    List<Pair> pairs = line.map((f) -> new Pair<>(f,1))
            .collect(Collectors.toList());
    pairs.forEach(f -> System.out.println(f.toString()));
    line.close();
Run Code Online (Sandbox Code Playgroud)

我现在如何输入文件编号?是否有lambda表达式可以执行此操作?或者我还需要其他东西吗?

Stu*_*rks 7

有几种方法可以做到这一点.Saloparenator的答案建议的计数器技术可以如下实现,使用一个AtomicInteger可变计数器对象并假设明显的Pair类:

List<Pair> getPairs1() throws IOException {
    AtomicInteger counter = new AtomicInteger(0);
    try (Stream<String> lines = Files.lines(Paths.get(FILENAME))) {
        return lines.parallel()
                    .map(line -> new Pair(line, counter.incrementAndGet()))
                    .collect(toList());
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是如果流并行运行,计数器将不会以与读取行相同的顺序递增!如果您的文件有几千行,则会发生这种情况.该Files.lines流源将行批量串起来,并将它们分派到多个线程,那么这将在并行数的批次,交织他们的电话incrementAndGet().因此,线将不按顺序编号.如果您可以保证您的流不会并行运行,那么它将起作用,但编写可能会顺序返回不同结果的流通常是一个坏主意.

这是另一种方法.因为无论如何都要将所有行读入内存,只需将它们全部读入列表即可.然后使用流对它们进行编号:

static List<Pair> getPairs2() throws IOException {
    List<String> lines = Files.readAllLines(Paths.get(FILENAME));
    return IntStream.range(0, lines.size())
                    .parallel()
                    .mapToObj(i -> new Pair(lines.get(i), i+1))
                    .collect(toList());
}
Run Code Online (Sandbox Code Playgroud)