如何将计数器插入 Stream<String>.forEach()?
How to insert a counter into a Stream<String> .forEach()?
FileWriter writer = new FileWriter(output_file);
int i = 0;
try (Stream<String> lines = Files.lines(Paths.get(input_file))) {
lines.forEach(line -> {
try {
writer.write(i + " # " + line + System.lineSeparator());
} catch (Exception e) {
e.printStackTrace();
}
}
);
writer.close();
}
我需要用行号写入行,所以我试图在 .forEach() 中添加一个计数器,但我无法让它工作。我只是不知道把 i++ 放在哪里;进入代码,随机乱搞到目前为止没有帮助。
您可以使用 AtomicInteger
作为可变 final
计数器。
public void test() throws IOException {
// Make sure the writer closes.
try (FileWriter writer = new FileWriter("OutFile.txt") ) {
// Use AtomicInteger as a mutable line count.
final AtomicInteger count = new AtomicInteger();
// Make sure the stream closes.
try (Stream<String> lines = Files.lines(Paths.get("InFile.txt"))) {
lines.forEach(line -> {
try {
// Annotate with line number.
writer.write(count.incrementAndGet() + " # " + line + System.lineSeparator());
} catch (Exception e) {
e.printStackTrace();
}
}
);
}
}
}
这是一个很好的例子,说明您应该使用老式的 for 循环。虽然 Files.lines()
专门给出了顺序流,但流可以无序地生成和处理,因此插入计数器并依赖于它们的顺序是一个相当糟糕的习惯。如果您仍然真的想这样做,请记住,在任何可以使用 lambda 的地方,您仍然可以使用完全匿名 class。匿名 classes 是正常的 classes,因此可以有状态。
因此在您的示例中,您可以这样做:
FileWriter writer = new FileWriter(output_file);
try (Stream<String> lines = Files.lines(Paths.get(input_file))) {
lines.forEach(new Consumer<String>() {
int i = 0;
void accept(String line) {
try {
writer.write((i++) + " # " + line + System.lineSeparator());
} catch (Exception e) {
e.printStackTrace();
}
}
});
writer.close();
}
如Java doc所述:
Any local variable, formal parameter, or exception parameter used but
not declared in a lambda expression must either be declared final or
be effectively final (§4.12.4), or a compile-time error occurs where
the use is attempted.
这意味着您的变量必须是最终的或实际上是最终的。您想在 forEach
中添加一个计数器,为此您可以使用 OldCurumudgeon 建议的 AtomicInteger
,这是 IMO 的首选方法。
我相信您也可以使用只有一个值的数组 0
,您可以将其用作计数器。检查并告诉我以下示例是否适合您:
public void test() throws IOException {
FileWriter writer = new FileWriter("OutFile.txt");
final int[] count = {0};
try (Stream<String> lines = Files.lines(Paths.get("InFile.txt"))) {
lines.forEach(line -> {
try {
count[0]++;
writer.write(count[0] + " # " + line + System.lineSeparator());
} catch (Exception e) {
e.printStackTrace();
}
}
);
writer.close();
}
}
FileWriter writer = new FileWriter(output_file);
int i = 0;
try (Stream<String> lines = Files.lines(Paths.get(input_file))) {
lines.forEach(line -> {
try {
writer.write(i + " # " + line + System.lineSeparator());
} catch (Exception e) {
e.printStackTrace();
}
}
);
writer.close();
}
我需要用行号写入行,所以我试图在 .forEach() 中添加一个计数器,但我无法让它工作。我只是不知道把 i++ 放在哪里;进入代码,随机乱搞到目前为止没有帮助。
您可以使用 AtomicInteger
作为可变 final
计数器。
public void test() throws IOException {
// Make sure the writer closes.
try (FileWriter writer = new FileWriter("OutFile.txt") ) {
// Use AtomicInteger as a mutable line count.
final AtomicInteger count = new AtomicInteger();
// Make sure the stream closes.
try (Stream<String> lines = Files.lines(Paths.get("InFile.txt"))) {
lines.forEach(line -> {
try {
// Annotate with line number.
writer.write(count.incrementAndGet() + " # " + line + System.lineSeparator());
} catch (Exception e) {
e.printStackTrace();
}
}
);
}
}
}
这是一个很好的例子,说明您应该使用老式的 for 循环。虽然 Files.lines()
专门给出了顺序流,但流可以无序地生成和处理,因此插入计数器并依赖于它们的顺序是一个相当糟糕的习惯。如果您仍然真的想这样做,请记住,在任何可以使用 lambda 的地方,您仍然可以使用完全匿名 class。匿名 classes 是正常的 classes,因此可以有状态。
因此在您的示例中,您可以这样做:
FileWriter writer = new FileWriter(output_file);
try (Stream<String> lines = Files.lines(Paths.get(input_file))) {
lines.forEach(new Consumer<String>() {
int i = 0;
void accept(String line) {
try {
writer.write((i++) + " # " + line + System.lineSeparator());
} catch (Exception e) {
e.printStackTrace();
}
}
});
writer.close();
}
如Java doc所述:
Any local variable, formal parameter, or exception parameter used but not declared in a lambda expression must either be declared final or be effectively final (§4.12.4), or a compile-time error occurs where the use is attempted.
这意味着您的变量必须是最终的或实际上是最终的。您想在 forEach
中添加一个计数器,为此您可以使用 OldCurumudgeon 建议的 AtomicInteger
,这是 IMO 的首选方法。
我相信您也可以使用只有一个值的数组 0
,您可以将其用作计数器。检查并告诉我以下示例是否适合您:
public void test() throws IOException {
FileWriter writer = new FileWriter("OutFile.txt");
final int[] count = {0};
try (Stream<String> lines = Files.lines(Paths.get("InFile.txt"))) {
lines.forEach(line -> {
try {
count[0]++;
writer.write(count[0] + " # " + line + System.lineSeparator());
} catch (Exception e) {
e.printStackTrace();
}
}
);
writer.close();
}
}