使用新的Java 8 Streams API解析多行行的CSV文件

我在一段时间后问了一个关于解析单个匹配行的CSV文件的问题 。 在下面显示的示例中,我使用bufferedreader来读取标题行作为第一步。 使用此行,我解析列名称,然后继续搜索匹配的行。 我需要搜索匹配行的过滤条件应该基于2列值,而下面显示的代码只返回1行 – 可能是因为我使用

.findFirst().get(); 

相反,我需要以下几行(但此代码无效)

 List rowCols = reader.lines() //.skip(1) .map((line) -> Arrays.asList(line.split(","))) .filter(list -> !list.get(col1Index).equalsIgnoreCase("0:00") && !list.get(col2Index).equalsIgnoreCase("0:00")) .findFirst().get(); 

因为这也只返回1行 – 但filter匹配多行。

我现在需要返回多个匹配的行,但我无法弄清楚正确的语法。

 String fileName = ... try (BufferedReader reader = new BufferedReader( new InputStreamReader(ftpClient. retrieveFileStream(fileName)))){ List columns = reader.lines() .findFirst() .map(line -> Arrays.asList(line.split(","))) .get(); // find the relevant sections from the CSV file // we are only interested in the row with the CA ServiceName int serviceNameIndex = columns.indexOf("ServiceName"); int col1Index = columns.indexOf("Column1"); int col2Index = columns.indexOf("Column2"); // we need to know the index positions of the columns // also note that due to using a BufferedReader we don't // have to re-read the csv file to extract the values List rowCols = reader.lines() //.skip(1) .map((line) -> Arrays.asList(line.split(","))) .filter(list -> list.get(serviceNameIndex).equalsIgnoreCase("service1")) .findFirst().get(); EnumMap params = new EnumMap(Parameter.class) {{ put(Parameter.ServiceName, rowCols.get(serviceNameIndex)); put(Parameter.Column1, rowCols.get(col1Index)); put(Parameter.Column2, rowCols.get(col2Index)); }}; params.put("service1", params); } 

我不确定你要完全实现什么,但我最好的猜测是你希望根据line.split(“,”)这一行的分割返回一个字符串列表。 您的代码不起作用,因为在您的filter方法之后,您返回整个字符串列表,但您需要进一步流式传输列表。 换句话说,您需要展平列表以获取其内容,如下所示

 List rowCols = reader.lines() .map((line) -> Arrays.asList(line.split(","))) .filter(list -> !list.get(col1Index).equalsIgnoreCase("0:00") && !list.get(col2Index).equalsIgnoreCase("0:00")) .flatMap(e->e.stream()) .collect(Collectors.toList()); 

这应该将每行的内容(您拆分的字符串)收集到一个列表中。

我认为你期望列表中的字符串列表能够获得所有匹配的行。 以下应该适用于这种情况:

  List> rowCols = reader.lines() //.skip(1) .map((line) -> Arrays.asList(line.split(","))) .filter(list -> !list.get(col1Index).equalsIgnoreCase("0:00") && !list.get(col2Index).equalsIgnoreCase("0:00")) .collect(Collectors.toList()); 

根据@Tunaki和@george的评论编辑