Parsing a CSV file for a multiple row rows using new Java 8 Streams API

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-23 04:51:47

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!