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

Implement counting variable with lambda expression java

我有一个关于 lambda 表达式的问题。我有一个 class 对,它应该包含一个字符串和一个整数。

Pair 从文件中获取字符串。 并且 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();

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

int cnt = 1;
List<Pair> pairs = line.map((f) -> new Pair<>(f,cnt++))
                       .collect(Collectors.toList());

我还没有尝试过,但可能会奏效。

另一种实用的方法是使用整数生成器压缩您的流列表

(我可以看到 java8 还没有,但它本质上是将两个列表的每个单元格合并成对列表,因此很容易实现)

您可以在 java8 here

中查看生成器示例

有几种方法可以做到这一点。 建议的计数器技术可以如下实现,使用 AtomicInteger 作为可变计数器对象并假设明显的 Pair class:

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());
    }
}

问题是,如果流是 运行 并行的,计数器将不会按照与读取行相同的顺序递增!如果您的文件有几千行,就会发生这种情况。 Files.lines 流源将对成串的行进行批处理并将它们分派给多个线程,然后这些线程将并行编号它们的批次,交错调用它们对 incrementAndGet()。因此,行不会按顺序编号。如果你能保证你的流永远不会 运行 并行,它就会起作用,但是编写可能 return 顺序与并行不同结果的流通常是一个坏主意。

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

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());
}