我有一个CSV文件,第一行包含标题。所以我认为使用Java 8流是完美的。
try (Stream<String> stream = Files.lines(csv_file) ){
stream.skip(1).forEach( line -> handleLine(line) );
} catch ( IOException ioe ){
handleError(ioe);
}
是否可以获取第一个元素,分析它然后调用forEach方法?像
这样的东西stream
.forFirst( line -> handleFirst(line) )
.skip(1)
.forEach( line -> handleLine(line) );
此外: 我的CSV文件包含大约1k行,我可以并行处理每一行以加快速度。除了第一行。我需要第一行来初始化项目中的其他对象:/ 那么打开BufferedReader,读取第一行,关闭BufferedReader以及使用并行流可能是快速的吗?
答案 0 :(得分:6)
通常,您可以使用迭代器来执行此操作:
Stream<Item> stream = ... //initialize your stream
Iterator<Item> i = stream.iterator();
handleFirst(i.next());
i.forEachRemaining(item -> handleRest(item));
在你的程序中,它看起来像这样:
try (Stream<String> stream = Files.lines(csv_file)){
Iterator<String> i = stream.iterator();
handleFirst(i.next());
i.forEachRemaining(s -> handleRest(s));
}
如果你得到1或0行,你可能想要添加一些错误检查,但这应该有用。
答案 1 :(得分:4)
这样做的好方法是让BufferedReader
读取您的文件,例如在Files.newBufferedReader(path)
的帮助下。然后,您可以拨打nextLine()
一次以检索标题行,并lines()
获取所有其他行的Stream<String>
:
try (BufferedReader br = Files.newBufferedReader(csv_file)){
String header = br.readLine();
// if header is null, the file was empty, you may want to throw an exception
br.lines().forEach(line -> handleLine(line));
}
这是有效的,因为第一次调用readLine()
会导致缓冲的阅读器读取第一行,因此,由于lines()
是通过读取行填充的流,因此它会在第二行开始读取线。处理结束时,try-with-resources也会正确关闭缓冲的阅读器。
潜在地,流管道可以并行运行,但是对于像这样的I / O绑定任务,我不希望任何性能提升,除非处理每一行的速度较慢。但在这种情况下要小心forEach
:它将同时运行,因此其代码需要是线程安全的。目前还不清楚handleLine
方法的作用,但通常情况下,您不需要forEach
,可能更喜欢mutable reduction collect
,这可以安全地用于并行流。
答案 2 :(得分:0)
我不认为在流管道中有这样做的好方法,但你可以使用流的迭代器来更好地控制迭代:
try (Stream<String> stream = Files.lines(csv_file) ){
Iterator<String> iter = stream.iterator();
if (iter.hasNext()) {
handleFirst(iter.next());
while (iter.hasNext()) {
handleLine(iter.next());
}
}
} catch ( IOException ioe ){
handleError(ioe);
}