Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparable and Comparator Interface in Java

I want to write a generic Pair class, which has two members: key and value. The only requirement to this class is that both key and value should implements the Comparable interface, otherwise Pair class will not accept them as type parameter.
First I code it like this:

public class Pair<T1 extends Comparable, T2 extends Comparable>

But the JDK 1.6 compiler will generate warning about this:

Comparable is a raw type. References to generic type Comparable<T> should be parameterized

Then I tried to add type parameters and the code now looks like this:

public class Pair<T1 extends Comparable<? extends Object>,
                  T2 extends Comparable<? extends Object>>

Now everything go well until I tried to generate an Comparator for Pair.(The following code is in Pair class)

public final Comparator<Pair<T1, T2>> KEY_COMPARATOR = new Comparator<Pair<T1, T2>>() {
        public int compare(Pair<T1, T2> first, Pair<T1, T2> second) {
            *first.getKey().compareTo(second.getKey());*
            return 0;
        }
    };

The code first.getKey().compareTo(second.getKey()); will generate an error saying:

The method compareTo(capture#1-of ? extends Object) in the type Comparable<capture#1-of ? extends Object> is not applicable for the  arguments (T1)

Anyone knows what does this error message mean?
Any hints on this topic are welcome.

UPDATE:
Here is the complete code:

public class Pair<T1 extends Comparable<? extends Object>, T2 extends Comparable<? extends Object>> {
    private T1 key;
    private T2 value;

    public static int ascending = 1;
    public final Comparator<Pair<T1, T2>> KEY_COMPARATOR = new Comparator<Pair<T1, T2>>() {
        public int compare(Pair<T1, T2> first, Pair<T1, T2> second) {
            int cmp = first.getKey().compareTo((T1)(second.getKey()));
            if (cmp > 0)  return ascending;
            return -ascending;
        }
    };
}

@MarvinLabs Can you explain a bit more why the compiler cannot make sure objects are compared to other objects of the same type. In the above code, second.getKey() returns T1 type, which is of the same type as first.getKey()

like image 391
cheng Avatar asked Dec 05 '22 14:12

cheng


1 Answers

I would declare my class as such:

public class Pair<T1 extends Comparable<T1>, T2 extends Comparable<T2>> 

Meaning that objects are comparable with objects of the same type as they are (your error means that the compiler cannot make sure objects are compared to other objects of the same type).


Your code with my edits compiles properly:

public class Pair<T1 extends Comparable<T1>, T2 extends Comparable<T2>> {
    private T1 key;
    private T2 value;

    public T1 getKey() {
        return key;
    }

    public T2 getValue() {
        return value;
    }

    public final Comparator<Pair<T1, T2>> KEY_COMPARATOR = new Comparator<Pair<T1, T2>>() {
        public int compare(Pair<T1, T2> first, Pair<T1, T2> second) {
            return first.getKey().compareTo(second.getKey());
        }
    };

    public static void test() {
        Pair<String, Integer> p1 = new Pair<String, Integer>();
        Pair<String, Integer> p2 = new Pair<String, Integer>();

        p1.KEY_COMPARATOR.compare(p1, p2);
    }
}

You should however make a separate class (or a static final class) of the comparator so that it is more intuitive to use & also does not increase the weight of each Pair instance.

like image 86
Vincent Mimoun-Prat Avatar answered Dec 30 '22 22:12

Vincent Mimoun-Prat