我对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();
我现在如何输入文件编号? 是否有lambda表达式可以执行此操作?或者我还需要其他东西吗?
答案 0 :(得分:7)
有几种方法可以做到这一点。 Saloparenator's answer建议的计数器技术可以如下实现,使用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());
}
}
问题在于,如果流并行运行,则计数器不会以与读取行相同的顺序递增!如果您的文件有几千行,则会发生这种情况。 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());
}
答案 1 :(得分:0)
答案 2 :(得分:-1)
int cnt = 1;
List<Pair> pairs = line.map((f) -> new Pair<>(f,cnt++))
.collect(Collectors.toList());
我还没有尝试过但可能有用。