Comparative and comparative interface in Java

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

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

But the JDK 1.6 compiler generates a 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 now the code looks like this:

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

Now everything is going well until I try to create a comparator for the couple. (The following code is for the 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; } }; 

Code first.getKey().compareTo(second.getKey()); generates an error:

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

Does anyone know what this error message means?
Any hints on this subject 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 little more why the compiler cannot make sure that objects are compared with other objects of the same type. In the above code, second.getKey() returns a T1 type that is of the same type as first.getKey()

+4
source share
3 answers

Let's first look at the interface design.

 public interface Comparable<T> { public int compareTo(T o); } 

This is pretty typical, we have to say. Therefore, if our class must implement it, we do this.

 pubilc class ICanComparteWithMyself implements Comparable<ICanComparteWithMyself> { public int compareTo(ICanComparteWithMyselfo) //code for compration } 

As we see the general type of parameter, we determine what we will work on, so for generics we act the same way

 public class ICanCompareMyGeneric<T> implements Comparable<T> { public int compareTo(T o) //code for compration } } 

In your case, whawt, we want it to ensure that common parameters are implemented, is proprietary Comparable, for this we need to do this

 public class MyGenericCanCompareToItself<T extends Comparable<T>> { } 

As we can see, this is often used. The expected limitation (or not) is that we can work on classes that implement Comparable for it of type self. If we had

  public class ICanCompareStrings implements Comparable<String> { public int compareTo(String o) //code for compration } } 

So, for the class MyGenericCanCompareToItself as a general parameter, we can use the class public MyGenericCanCompareToItself , but not ICanCompareStrings .

EDIT:

So, when we covered the basics, we can solve your problem

The description of your class is as follows:

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

This is not a big deal, as it is less than <?>

This description says:

I am a Pair class that works with two universal parameters that can use comparison compared to what I don't know.

With this code, you cannot progress until the general parameters are aware of it, and then operate there so that you end up with something like this.

first.getKey.compareTo(null);

And that's why the code does not compile when you try to cast, the expected type is null.


To change what you need to determine what type of your general options should be comparable.

For example, you can compare on your sheet

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

This description says:

I am a Pair class that works with two parameters, each of which can be compared with itself.

And this is what you are probably looking for, besides, they can be compared with something that could be a superclass T1 or T2

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

This description says:

I am a Pair class that works with two parameters, each of which can be compared with the classes that deliver them.

I hope this helps you with generics; -).

+8
source

I would declare my class as such:

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

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


Your code with my changes compiles correctly:

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

However, you must make a separate class (or static final class) of the comparator so that it is more intuitive to use and also does not increase the weight of each instance of the pair.

+9
source

if you knew the differences between:

 List<Object> 

and

 List<String> 

... it will be easier. basically, they are two different types in java (not the "same" type of list as you think).

The general type of โ€œlogicโ€ is not very simple, as you think in your mind or as it seems.

I think you should declare your class "Pair" as follows:

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

since you have already done the T1 "T2" mapping, why can you implement a comparator?

if you want to use "Collections.sort (myCollection, myComparator)" then you do not need to declare that "T1" and "T2" are "comparable" ... just make sure your "KEY_COMPARATOR" accepts them ...

In any case, there is redundancy in the code.

-1
source

Source: https://habr.com/ru/post/1441486/


All Articles