Say*_*iss 5 java lambda java-8
bufferedReader.readLine()
很长一段时间以来,我习惯使用 lambda 逐行解析文件(比 lambda 简洁得多)。但今天我遇到了一个问题:为每一行添加一个行号。
它需要一个计数器,但 lambda 中的变量实际上应该是最终的。最后,我用 int 数组破解了它。
代码:
public static void main(String[] args) {
int[] counter = new int[1];
counter[0] = 0;
try (Stream<String> lines = Files.lines(Paths.get("/tmp/timeline.txt"), Charset.defaultCharset())) {
lines.limit(10).forEachOrdered(line -> {
line = line.trim();
counter[0] ++;
System.out.println("Line " + counter[0] + ": " + line);
});
} catch (IOException e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Line 1: p 5714026 wEkQ
Line 2: v 8235889
Line 3: v 6534726
...
Run Code Online (Sandbox Code Playgroud)
我的问题是,如何避免我的黑客攻击并优雅地解决该问题?
对于非功能性任务,没有优雅的功能性解决方案。您可能考虑的第一个,只是求助于普通的匿名内部类:
\n\nString path = "/tmp/timeline.txt";\ntry(Stream<String> lines = Files.lines(Paths.get(path), Charset.defaultCharset())) {\n lines.limit(10).forEachOrdered(new Consumer<String>() {\n int counter = 0;\n public void accept(String line) {\n System.out.println("Line " + counter++ + ": " + line.trim());\n }\n });\n} catch (IOException e) {\n e.printStackTrace();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n优点是它不会在实际情况下假装起作用,并且变量的范围counter
具有此任务所需的最小范围。
如果您要做的不仅仅是打印这些编号行,并且需要一个与所有流操作兼容的解决方案,那么重新实现流源是一个直接的解决方案:
\n\nstatic Stream<String> numberedLines(Path path, Charset cs) throws IOException {\n BufferedReader br = Files.newBufferedReader(path, cs);\n return StreamSupport.stream(new Spliterators.AbstractSpliterator<String>(\n Long.MAX_VALUE, Spliterator.ORDERED|Spliterator.NONNULL) {\n int counter;\n public boolean tryAdvance(Consumer<? super String> action) {\n String line;\n try {\n line = br.readLine();\n if(line==null) return false;\n action.accept("Line " + counter++ + ": " + line.trim());\n return true;\n } catch (IOException ex) {\n throw new UncheckedIOException(ex);\n }\n }\n }, true).onClose(()->{ try { br.close(); }\n catch (IOException ex) { throw new UncheckedIOException(ex); }\n });\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n当然,这不像单个 lambda 表达式那么简单,但是使用这种可重用的方法,您可以毫无问题地使用所有流操作,例如
\n\nString path = "/tmp/timeline.txt";\ntry(Stream<String> lines = numberedLines(Paths.get(path), Charset.defaultCharset())) {\n lines.skip(10).limit(10).forEachOrdered(System.out::println);\n} catch(IOException e) {\n e.printStackTrace();\n}\n
Run Code Online (Sandbox Code Playgroud)\n
归档时间: |
|
查看次数: |
2714 次 |
最近记录: |