Sameer
Sameer

Reputation: 807

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));
        }
    }
}

Upvotes: 1

Views: 122

Answers (4)

Eran
Eran

Reputation: 393841

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.

Upvotes: 2

GrabNewTech
GrabNewTech

Reputation: 641

Length of string for both "Shameer" and "Aameer" are same. So java compareTo method will consider both value (considering length) are same. So both object are considered equal in sorting.

While adding a object to key in Map interface the value should be unique this violated the compareTo method. So not able to add the above values.

As you already aware that in Map interface duplicate keys is not allowed.

I have explained with the simple example. If key value are same then you cannot add the values into Map interface.

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

public class Student2  {

public static void main(String[] args) {

    Map<String, Integer> mp = new TreeMap<String, Integer>();

    mp.put("Sameer", 1);
    mp.put("Sameer", 2);

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

Result: Sameer

Upvotes: 0

Bastian J
Bastian J

Reputation: 372

since compare() returns 0 for both keys, they are considered equal in the sorting. See https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html to und er stand why it is strictly recommended to habe compare behaving consistent with equals(), but the bottom line is that the second key is not added since it is considered equal to the first.

The solution is to make your compare consistent with equals by adding any kind oft tie breaker. E.g., if the two strings are not equal, but habe the same length, return their lexicographic order, or compute a hash based in the actual characters.

Upvotes: 1

Arty Jiang
Arty Jiang

Reputation: 46

The answer is in TreeMap.put. With your override of compareTo method the second put does only replace the value for the key because the two strings have same length.

Upvotes: -1

Related Questions