How to convert csv to a map using Java 8 Stream

13,816

Solution 1

Ok, I added lines.close() and removed any whitespace from the csv and it works! Strange, considering the csv got parsed fine in my other method. Here's what it looks like:

public static Map<String, String> getMapFromCSV(final String filePath) throws IOException{

        Stream<String> lines = Files.lines(Paths.get(filePath));
        Map<String, String> resultMap = 
                lines.map(line -> line.split(","))
                     .collect(Collectors.toMap(line -> line[0], line -> line[1]));

        lines.close();

        return resultMap;
    }

Solution 2

Try-with-resources with AutoCloseable

As commented by fge, using try-with-resources makes this easier.

Here is the code from your Answer but using try-with-resources to automatically close a Stream that is also AutoCloseable. And some added SPACE characters for breathing room.

public static Map<String, String> getMapFromCSV(final String filePath) throws IOException{

    try (
        Stream < String > lines = Files.lines( Paths.get( filePath ) );
    )
    {
        Map < String , String > resultMap = 
                lines.map( 
                         line -> line.split( "," ) 
                     )
                     .collect(
                         Collectors.toMap( line -> line[0] , line -> line[1] )
                     );
        return resultMap;
    }
    // The `Stream` named `lines` is automatically closed at this point by the try-with-resources.
}

When the {…} block of the try-with-resources ends, any resources opened in the try are automatically closed, in reverse order of their opening. This is true whether flow-of-control leaves the block gracefully upon completion, or abruptly due to an exception or a return (as seen in your code). See discussion on this Question, Try-with-resources and return statements in java.

Share:
13,816
ark234
Author by

ark234

Updated on June 27, 2022

Comments

  • ark234
    ark234 almost 2 years

    I'm trying to create a simple parsing util that converts a two-column CSV file and put it into a map.

    public Map<String, String> getMapFromCSV(final String filePath) throws IOException {
        return Files.lines(Paths.get(filePath))
                    .map(line -> line.split(","))
                    .collect(Collectors.toMap(line -> line[0], line -> line[1]));
    }
    

    As you can see, I'm creating a stream of strings, delimiting each line on a comma and transforming it into a string array, and finally mapping key to index 0 and value to index 1.

    @Test
    public void testGetMapFromCSV() throws IOException{
        actual = util.getMapFromCSV(filePath).get("AL");
        expected = "ALABAMA";
    
        assertEquals(expected, actual);
    }
    

    For some reason, when I run this test, the actual value is null. I ruled out invalid filePath because it's working fine in another unit test, and the key value is present in the CSV. I've been staring at it for a few hours now, figured maybe someone here could point out my error.

    Also, I'm fairly new to Java 8, so if anyone knows a better/cleaner way of writing this, I'd appreciate the feedback.

  • Fabio Lopez
    Fabio Lopez almost 3 years
    Thanks for sharing! Do you know of a way to do it with streams while removing duplicates?