Search code examples
javatreemap

What happens to the values of duplicate keys in a tree map


I have a text file which is read into a Tree Map. The Text File contains a list of students and their marks.

Harry 10
Sam    8
John   7
Harry  8
Sam    9

I have tried writing this code, which reads a file, stores it in the Tree Map and displays it on the console.

Scanner scanner = new Scanner(new FileReader("marks.txt"));
    TreeMap<String, Integer> students = new TreeMap<String, Integer>();
    while (scanner.hasNextLine()) {
        String[] columns = scanner.nextLine().split("\\s+");
        students.put(columns[0], Integer.parseInt(columns[1]));
    }
    System.out.println("Alpha Order");
    // Iterate over TreeMap
    for (String key : students.keySet()) {
        System.out.println(key + " :: " + students.get(key));
    }

The output I get on the console after executing the code is

Alpha Order
Harry :: 10
John :: 7
Sam :: 9 

I need the other values for further computations. is it possible to have an output like

Harry :: 10 8
John  ::  7
Sam   ::  9 8

Solution

  • As others have pointed out, the values will be replaced since a Map only allows one key -> value mapping.

    The easiest way of mapping multiple values to a key is to use a multi(value)map. I prefer Guava for this:

    Scanner scanner = new Scanner(new FileReader("marks.txt"));
    TreeMultimap<String, Integer> students = TreeMultimap.create();
    while (scanner.hasNextLine()) {
        String[] columns = scanner.nextLine().split("\\s+");
        students.put(columns[0], Integer.parseInt(columns[1]));
    }
    System.out.println("Alpha Order");
    // Iterate over TreeMap
    for (String key : students.keySet()) {
        System.out.println(key + " :: " + String.join(", ", students.get(key)));
    }
    

    But if you can't add dependencies you can use a TreeMap<String, TreeSet<Integer>>:

    Scanner scanner = new Scanner(new FileReader("marks.txt"));
    TreeMap<String, TreeSet<Integer>> students = new TreeMap<>();
    while (scanner.hasNextLine()) {
        String[] columns = scanner.nextLine().split("\\s+");
        String student = columns[0];
        TreeSet<Integer> set;
        if(students.containsKey(student)) {
            // A set already exists in the map for this student,
            // append to it
            set = students.get(student);
        } else {
            // No set exists in the map for this student,
            // create a new one and put it in the map
            set = new TreeSet<>();
            students.put(student, set);
        }
        set.add(Integer.parseInt(columns[1]));
    }
    System.out.println("Alpha Order");
    // Iterate over TreeMap
    for (String key : students.keySet()) {
        System.out.println(key + " :: " + String.join(", ", students.get(key)));
    }
    

    Note that these two are using sets so won't allow duplicate key -> value mappings. I.e. you can't get this output:

    Harry :: 10 8 8
    John  ::  7 7
    Sam   ::  9 9 8
    

    That's easy to achieve with the latter solution though by just replacing the TreeSet with an ArrayList.