Search code examples
javacsvcollectionspojo

Java - Load CSV to Complex Nested Map with POJO


I have CSV file which is in the form as below

student, year, subject, score1, score2, score3
Alex, 2010, Math, 23, 56, 43
Alex, 2011, Science, 45, 32, 45
Matt, 2009, Art, 34, 56, 75
Matt, 2010, Math, 43, 54, 54

I'm trying to find an optimal solution to read the CSV file and load it to a map for lookup purposes i.e. Map<String, Map<String, List<SubjectScore>>>. The first string key is for student, the next string key is for year.

class SubjectScore {
  private String subject;
  private int score1;
  private int score2;
  private int score3;
}

If there is a better way to store the CSV structure to get SubjectScore based on student and year information, I'll like to know that.


Solution

  • You can add some constructors to SubjectStore and use streams to read the file contents and convert it to your required data structure:

    public class SubjectScore {
        private final String subject;
        private final int score1;
        private final int score2;
        private final int score3;
    
        SubjectScore(String subject, int s1, int s2, int s3) {
            this.subject = subject;
            this.score1 = s1;
            this.score2 = s2;
            this.score3 = s3;
        }
    
        SubjectScore(String subject, String s1, String s2, String s3) {
            this(subject, Integer.parseInt(s1), Integer.parseInt(s2), Integer.parseInt(s3));
        }
        // getters/toString
    }
    

    Map<String, Map<String, List<SubjectScore>>> res = Files.lines(Path.of("data.csv"))
                .skip(1) // skip header line
                .map(line -> line.split("\\s*,\\s*")) // get columns
                .collect(
                    Collectors.groupingBy(arr -> arr[0], TreeMap::new, // key: student
                    Collectors.groupingBy(arr -> arr[1], TreeMap::new, // key: year
                    Collectors.mapping(arr -> new SubjectScore(arr[2], arr[3], arr[4], arr[5]), Collectors.toList())
                )));