问题
I asked a question some time back about parsing CSV files for a single matching row. In the example shown below, I use a bufferedreader to read the header row as the first step. Using this row, I parse the column names and then proceed to search for matching rows. The filter criteria I need to search for the matching row should be based on 2 column values, instead the code shown below only returns the 1 row - presumably because I use
.findFirst().get();
Instead I need something along the following lines (but this code is not valid)
List<String> 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();
as this also just returns 1 row - however the filter matches multiple rows.
I now need to return multiple matching rows but I cannot figure out the correct syntax.
String fileName = ...
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(ftpClient.
retrieveFileStream(fileName)))){
List<String> 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<String> rowCols = reader.lines()
//.skip(1)
.map((line) -> Arrays.asList(line.split(",")))
.filter(list -> list.get(serviceNameIndex).equalsIgnoreCase("service1"))
.findFirst().get();
EnumMap<Parameter, String> 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);
}
回答1:
I am not sure what you are trying to achieve exactly but my best guess is that you would like to return a list of strings based on the splitting of the line like line.split(","). Your code doesn't work because after your filter method you return the whole list of strings but you need to further stream the list. In other words you need to flatten the list to get its contents like below
List<String> 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());
This should collect the contents(strings which you've split) of each line into a single list.
回答2:
I think you are expecting a List of string in a list to get all the matching rows. The below should work in that case:
List<List<String>> 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());
Edited as per comment by @Tunaki and @george
来源:https://stackoverflow.com/questions/37865492/parsing-a-csv-file-for-a-multiple-row-rows-using-new-java-8-streams-api