Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
655 views
in Technique[技术] by (71.8m points)

generics - 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()

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...