0

I want to iterate though this 2d array and put values into a Map of Strings as key and list of strings Basically i have this but i am not able to modify the value list to add another value in the case where a key already exists

  static float bestAverageStudent(String[][] students) {
        Map<String, List<String>> grades = new HashMap<>();
        for (int row = 0; row < students.length; row++) {
            for (int col = 0; col < students[row].length; col++) {
                if (grades.get(students[row][0]) == null) {
                    grades.put(students[row][0], Arrays.asList(students[col][1]));
                } else {
                    List<String> strings1 = grades.get(students[row][0]);
                    strings1.add( students[col][1]);               //It fails when i try to add to the list
                    grades.put(students[row][0], new ArrayList<>(strings1));
                }
            }
        }
        System.out.println(grades);
        return 0;

Here is the array

 public static String students[][] = new
            String[][]{{"jerry", "65"},
            {"bob", "91"},
            {"jerry", "23"},
            {"Eric", "83"}};

I would like to keep this record in a map where values are a list of grades by one student

Thank you

0xh3xa
  • 4,801
  • 2
  • 14
  • 28
valik
  • 2,014
  • 4
  • 24
  • 55

2 Answers2

3

The first problem comes from Java List.add() UnsupportedOperationException , which gives you a Returns a fixed-size list, you need to wrap it in an ArrayList like new ArrayList<>(Arrays.asList(...))

But also, you don't need to double-iterate your array, as you know the structure of, it, just iterate to the first arrays, and access the 2 values :

Map<String, List<String>> grades = new HashMap<>();
for (int row = 0; row < students.length; row++) {
    String name = students[row][0];
    String grade = students[row][1];
    if (!grades.containsKey(name)) {
        grades.put(name, new ArrayList<>(Arrays.asList(grade)));
    } else {
        List<String> strings1 = grades.get(name);
        strings1.add(grade);
        grades.put(name, new ArrayList<>(strings1));
    }
}

Using Streams

Map<String, List<String>> grades = Arrays.stream(students)
                .collect(groupingBy(values -> values[0], mapping(values -> values[1], toList())));
azro
  • 53,056
  • 7
  • 34
  • 70
  • this is good, but why will double iterate not work, i see that i placed the values repeatedly into the value field of the map, somehow iterating twice was the first idea that came to me, could you explain why it is wrong – valik Mar 22 '20 at 12:00
  • 1
    @valik you used `students[col][1]` instead of `students[row][1]` and as you're doing the insert for each value of the subarray (2) you'll duplicate for all – azro Mar 22 '20 at 12:26
2

Because of Arrays.asList(...) return Implementation of AbstractList, which causes the issue.

Try this updated code:

Map<String, List<String>> grades = new HashMap<>();
for (int row = 0; row < students.length; row++) {
    for (int col = 0; col < students[row].length; col++) {
        if (!grades.containsKey(students[row][0])) {
            List<String> list = new ArrayList<>();
            list.add(students[col][1]);
            grades.put(students[row][0], list);
        } else {
            List<String> strings1 = grades.get(students[row][0]);
            strings1.add(students[col][1]);//It fails when i try to add to the list
            grades.put(students[row][0], new ArrayList<>(strings1));
        }
    }
}
System.out.println(grades);
return 0;
0xh3xa
  • 4,801
  • 2
  • 14
  • 28