akshit bhatia
akshit bhatia

Reputation: 395

how to implement Treemap with comparator?

The error that i was facing in this Question has been solved and is written below in answer section.

The problem was that the below definition of TreeMap is throwing a compiler error and I wanted to know the reason.

Comparator<Student> comparator=new Comparator<Student>() {

            @Override
            public int compare(Student o1, Student o2) {
                // TODO Auto-generated method stub
                if(o1.roll<=o2.roll)
                    return -1;
                else return 1;
            }
        };
        TreeMap<Integer, Student> map=new TreeMap<>(comparator);

I dont understand the reason this implementation of Treemap is wrong. Can anyone please explain me about what is going on in here?

Upvotes: 1

Views: 2996

Answers (2)

Anonymous
Anonymous

Reputation: 86232

TL;DR: A comparator for a TreeMap<Integer, Student> needs to compare Integers, not Students.

A TreeMap<Integer, Student> maps from integers (“the keys”) to student objects (“the values”) and keeps the mappings sorted by the integers. Therefore the constructor does not accept a Comparator<Student> as argument.

According to the documentation of TreeMap<K,V>, the constructor taking a comparator as argument is declared as

    TreeMap​(Comparator<? super K> comparator)

This means that the comparator must work on type K, the type of the keys, or some supertype of K. In your case, K is Integer.

Since the Integer class already defines an ordering, the so-called natural ordering, I suggest you don’t need a comparator at all:

    TreeMap<Integer, Student> map = new TreeMap<>();        

If you wanted to store the students by their roll number, just insert them like this:

        Student me = new Student();
        map.put(me.roll, me);

The side effect will be that the map is sorted by roll.

PS The information in the answer by John Kugelman is correct too, a comparator needs to handle three cases. And Comparator.comparingInt(s -> s.roll) or Comparator.comparingInt(Student::getRoll) (if the class has such a getter) is recommended, not only for the terseness, even more because it’s less error-prone.

Upvotes: 2

John Kugelman
John Kugelman

Reputation: 361585

compare() needs to handle three cases: less than, greater than, and equal. You need to return 0 when they're equal.

if (o1.roll == o2.roll) {
    return 0;
}
else if (o1.roll < o2.roll) {
    return -1;
}
else {
    return 1;
}

Integer.compare(int x, int y) can do all of this for you:

public int compare(Student o1, Student o2) {
    return Integer.compare(o1.roll, o2.roll);
}

In Java 8 you can create the entire comparator in a single line:

Map<Integer, Student> map = new TreeMap<>(Comparator.comparingInt(s -> s.roll));

Upvotes: 6

Related Questions