Search code examples
javacollectionsoverloadingtreemap

Why do I get only one Key in Keyset while Overloading Comparable in TreeMap in Java


  1. I Tried to do custom Ordering in my TreeMap based on length of string. Why am I getting only one Key if the length of the string is same despite being different strings.

  2. How do I fix this and what are the implications for the equals meth0d, will it ever be used or will compareTo take its place.

The code:

import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

public class Student implements Comparable {
    int RollNo;
    String Name;
    public Student(int RollNo, String Name) {
        this.RollNo = RollNo;
        this.Name = Name;
    }

    public int compareTo(Object arg0) {
        Student str = (Student) arg0;
        return Integer.valueOf(str.Name.length()).compareTo(Integer.valueOf(this.Name.length()));
    }

    public static void main(String[] args) {
        Map<Student, Integer> mp = new TreeMap<Student, Integer>();
        mp.put(new Student(1, "Sameer"), 1);
        mp.put(new Student(2, "Aameer"), 2);

        for(Student st : mp.keySet()){
            System.out.println((st.Name));
        }
    }
}

Solution

  • Your compareTo method compares the lengths of the name Strings instead of their content, so Students having names with same length are considered identical by the TreeMap.

    In other words, the Comparable or Comparator used by the TreeMap determines both ordering and uniqueness of the keys.

    You can solve the issue by ordering the TreeMap by both name length and name content (when the lengths are equal) :

    public int compareTo(Object arg0) {
    
        Student str = (Student) arg0;
    
        int lengthComp = Integer.valueOf(str.Name.length()).compareTo(Integer.valueOf(this.Name.length()));
        if (lengthComp == 0) {
            // compare names if the lengths are equal
            return str.Name.compareTo(this.Name);
        } else {
            return lengthComp;
        }
    }
    

    Besides that, it's better for your class to implement Comparable<Student>, which will allow your compareTo method to accept a Student argument.

    How do I fix this and what are the implications for the equals meth0d, will it ever be used or will compareTo take its place.

    equals is not used by TreeMap, and compareTo indeed takes its place.