I have a litte problem and was wondering how to solve it. I have a generic class Tuple<A,B> and now I would like to sort their tuples according to A and B. It should look like this:
Unsorted:
(1,5)
(2,8)
(6,8)
(1,4)
(2,4)
Sorted:
(1,4)
(1,5)
(2,4)
(2,8)
(6,8)
For that reason I thought of implementing a generic compare method (public int compareTo(Tuple<A, B> other)) in the Tuple class. The only problem is that all objects that you could parameterize the class for (e.g. A=Integer, B=String) have to implement the compareTo method too in order for this whole thing to work.
Is there a way to ensure that all objects the Tuple can hold implement the Comparable interface?
Or are there any other suggestions on how to solve this problem?
Thanks
If you declare the class as
public class Tuple<A extends Comparable<? super A>,
B extends Comparable<? super B>> { ...
then that ensures that both A and B are self-comparable. You can then call compareTo() on any object of type A or B that you have in the class.
You could use recursive type bounds (see also Item 27 of Effective Java) to specify that the components of the tuple extend Comparable, like so:
public class Tuple<A extends Comparable<? super A>, B extends Comparable<? super A>> implements Comparable<Tuple<A, B>> {
A valueA;
B valueB;
#Override
public int compareTo(Tuple<A, B> tuple) {
// Implement comparison logic
return 0;
}
}
This allows you to specify different types for the components of the tuple (Tuple<Integer, String>).
This should do the trick. Any class you specify will have to extend Comparable.
public class Tuple<? extends Comparable> {
}
Related
TreeSet(Collection<? extends E> c) constructor was defined as:
Constructs a new tree set containing the elements in the specified collection, sorted according to the natural ordering of its elements. All elements inserted into the set must implement the Comparable interface. Furthermore, all such elements must be mutually comparable: e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the set.
Is it possible syntactically enforce that E in Collection<? extends E> implements Comparable? In above JavaDoc this check postponed to execution time...
Yes, but not with constructors; you'd have to expose a factory method, which can impose constraints on the collection type beyond those imposed by the class as a whole. For example, they could've written
public class TreeSet<E> { ...
public static <E extends Comparable<? super E>> TreeSet<E>
create(Collection<? extends E> collection) {
TreeSet<E> set = new TreeSet<E>();
set.addAll(collection);
return set;
}
...
}
You can make your project require this by using a factory method like this:
public static <T extends Comparable<? super T>> SortedSet<T> safeSortedSet() {
return new TreeSet<T>();
}
Then is code:
Set<String> pass = safeSortedSet();
Set<Foo> fail = safeSortedSet();
Second line produces compile error:
Error:(99, 38) java: incompatible types: inference variable T has incompatible bounds
equality constraints: Test.Foo
upper bounds: java.lang.Comparable
From Tavian Barnes comment:
They could have done class TreeSet<E extends Comparable<? super E>>, but then you wouldn't have been able to use custom comparators for unorderable types. I can't think of a good way to enforce this only on a single constructor
So it is possible with <E extends Comparable<? super E>> syntax, but unfortunately each generic extends / super syntax make ultimate restriction on any other type declaration with E.
In case TreeSet look to Creating a TreeSet with a non-Comparable class: why a run-time exception, rather than compile-time error?
Thanks for all who helps with answer!
I have the following piece of code
public static <T extends Comparable<T>> T max(List<T> list){
Iterator<T> iter = list.iterator();
...
// code for finding the max element in the list
...
}
My question is, what is the need for the recursive type bound in this case? As far as my understanding, T extends Comparable < T > means that, T can be compared only with T itself. This comes from the fact that, Class 'T' implements Comparable<T> and so,
class MyClass implements Comparable<MyClass>{
}
If I am wrong here, feel free to correct me.
So now coming to the actual doubt, why do we need to specify < T extends Comparable < T > > ? Any ways the argument List<T> list is going to contain the elements of same type. i.e., suppose I pass a parameter of type List < MyClass2 > , then all the elements are going to be of same type, i.e. MyClass2..
So what is the implication of recursive type bound?
Thanks in advance.
Why do you need to specify <T extends Comparable<T>>? Because Comparable does not require that an implementing class be comparable with itself. You could in theory write something like
class Circle extends Shape implements Comparable<Integer> {
...
}
Since Comparable itself does not make that restriction, you have to on your end when writing the function. However, the given bound is more restrictive than you need it to be. You could make the call
public static <T extends Comparable<? super T>> T max(List<T> list) {
...
}
That would mean T is comparable to some superclass of itself. The reason you want this is given in the Fruit example of rgettman. T is still always comparable to itself, but the comparable does not have to be defined with respect to T itself.
You may have a class hierarchy that forces subclasses to be Comparable to a supertype. For example, you may have
class Fruit extends Comparable<Fruit>
so every piece of Fruit is comparable to another piece of Fruit. Then you have
class Apple extends Fruit ...
class Banana extends Fruit ...
Each subclass is a Fruit, so they are all Comparable<Fruit>, and not Comparable<Apple> and not Comparable<Banana>.
This allows you to find the maximum Fruit (probably a bad example, what's the maximum Fruit?) in a List<Apple>:
List<Apple> apples = getApples();
Fruit maximum = max(apples);
without it having to be a List<Fruit>.
As has been pointed out in comments, it's better for the max method to be:
public static <T extends Comparable<? super T>> T max(List<T> list){
So that each of the following works:
List<Apple> apples = getApples();
Apple maxAppleOfApples = max(apples);
Fruit maxFruitOfApples = max(apples);
List<Banana> bananas = getBananas();
Banana maxBananaOfBananas = max(bananas);
Fruit maxFruitOfBananas = max(bananas);
List<Fruit> fruits = getFruit();
Fruit maxFruitOfFruit = max(fruits);
Declaration like this :
class A<X extends Number & List> { }
is allowed.Whereas declaration like this is not allowed.
class A<? extends Number & List> { }
Is there any logical explanation about why Java restricts us to do that?
& what's the actual difference between
<T extends Number>
& <? extends Number>?
If you used <? extends Number & List>, then you wouldn't be able to do anything with the type parameter. It'd be completely useless.
Similarly, ? extends Number lets you deal with the special case when you don't need to refer to the type that extends number, and you don't need to give it a name.
The whole point of a type parameter like T is so that you can use it as a type inside the class. What would a wildcard there even mean? If you can't use it anywhere, why have a type parameter at all?
Generic class and interface declarations want type parameters, such as T or U. ? is a wildcard, better used for method parameters that are themselves generic:
class Foo<T extends Number & List> {
void doStuff(List<T> items) {
// ...
}
void doMoreStuff(List<? extends OutputStream> streams) {
// ...
}
}
doStuff() indicates that it wants to operate on a List<T> where T is the type parameter on class Foo. So:
class Weird extends Number implements List {
//
}
Foo<Weird> f = new Foo<Weird>();
f.doStuff(...); // wants a List<Weird>
If we called doMoreStuff() on f, we could hand it something of type List<OutputStream>, List<FilterOutputStream>, List<ByteArrayOutputStream>, etc.
I have some sorting methods that in order to work they need to accept an object that has the compareTo defined.
The following as part of the generic definition:
private static <SomeType extends Comparable<? super SomeType>>
void doSomeSort(SomeType[] a, int left, int right){
seems to do the trick.
My problem is that I don't really understand what the
<SomeType extends Comparable<? super SomeType>>
actually defines.
It means that you can substiture a type that is an interface that extends Comparable that is instanciated by itself...
I don't get.
Can you please help on clarifying this definition?
This means:
SomeType is a class that extends Comparable<SomeType> or Comparable<Any type that is a superclass or super interface of SomeType>.
The reason of ? super SomeType is that the sort procedure is able to sort an array of SomeType instances if SomeType is able to compare itself to other SomeType instances. If it happens that SomeType extends SomeSuperType, and that any SomeSuperType instance is able to compare itself to other SomeSuperType instances, the sort will compare them without problems.
Ultimately, all you really need to know is that it means:
SomeType x = ...;
SomeType y = ...;
int comparison = x.compareTo(y);
will compile.
More precisely, it means that SomeType implements Comparable<T> for some type T which is in the inheritance hierarchy of SomeType... without you having to specify what the T is but the upshot is that the code above works :)
It translates to:
the type SomeType must extend or implement the class Comparable
the class Comparable itself, in this case, takes some type as parameter, let's call it T.
type T must be SomeType or a superclass of SomeType.
A classic type that fits this pattern is Integer, since it implements Comparable<Integer>.
<SomeType extends Comparable<? super SomeType>>
Comparable is always of a special template type.
So Comparable<String> is something that can be compared to a String, Comparable<BigInteger> is something that can be compared to a BigInteger, and so on.
What's expected here is a SomeType which derives from Comparable<T>. Meaning that SomeType is comparable to other instances. The most trivial thing would be
<SomeType extends Comparable<SomeType>>
Should be clear till now.
Everything thats now added is a simple super keyword.
This means, SomeType needs to be comparable to everything that is of type SomeType or anything above in the derivation hierarchy.
This basically has one advantage: You can later derive your own/additional types from SomeType and this method will still be downward compatible!
Awesome, eh?
For example:
class SomeTypeSuper { ... }
class SomeType extends SomeTypeSuper { ... }
// Now, in your code both is valid:
// Asuming the method `yourMethod` expects a `<SomeType extends Comparable<? super SomeType>>` as parameter.
yourMethod(new SomeTypeSuper()); // This wouldn't be valid if we had used Comparable<SomeType>
yourMethod(new SomeType());
Float is a subclass of Number. We could declare it like so:
class Float extends Number implements Comparable<Float>
But in fact, our Float class is way broader than that. The float class knows how to compare itself with Integers, Bignums, Doubles, etc etc. In fact, our float class knows how to compare itself to *any( number.
class Float extends Number implements Comparable<Number>
class Integer extends Number implements Comparable<Number>
In fact: any number class needs to do this, so the real declaration sare
class Number implements Comparable<Number>
class Integer extends Number
class Float extends Number
Now, the Comparable interface is cool with this. If it wasn't wildcarded, then Floats and Integers wouldn't be able to be Comparable.
But since it is, you can go:
Comparable<Number> array[] = new Comparable<Number>[10];
array[0] = Float.getValue(10);
array[1] = Integer.getValue(11);
sort(array, 0, 1);
You can't do this without the >? super T>.
What is the difference in following 2 lines?
public static <T extends Comparable<? super T>> int methodX(List<T> data)
public static <T> int methodX(List<? extends Comparable<? super T>> data)
Your first option is a "stricter" parametrisation. Meaning, you're defining the class T with a bunch of restrictions, and then use it later on with List. In your second method, the parameter class T is generic with no conditions, and the Lists class parameter is defined in terms of the parameter T.
The second way is syntactically different as well, with a ? instead of the first option's T, because in the parameter definition you aren't defining the type parameter T but rather using it, so the second method cannot be as specific.
The practical difference that comes out of this is one of inheritance. Your first method needs to be a type that is comparable to a super class of itself, whereas the second type need only be comparable to an unconditional/unrelated T:
public class Person implements Comparable<Number> {
#Override
public int compareTo(Number o) {
return 0;
}
public static <T extends Comparable<? super T>> int methodX(List<T> data) {
return 0;
}
public static <T> int methodY(List<? extends Comparable<? super T>> data) {
return 0;
}
public static void main(String[] args) {
methodX(new ArrayList<Person>()); // stricter ==> compilation error
methodY<Object>(new ArrayList<Person>());
}
}
If you change the Comparable of Person to be able to compare Object or Person (the inheritance tree of the base class) then methodX will also work.
To the callers, the 2nd version is roughly equivalent to
public static <T, X extends Comparable<? super T>> int methodX(List<X> data)
Suppose a caller calls it with an arg whose concrete type List<Foo>. Type inference will conclude that X=Foo. Then we get a new equation about T from X's bound
=>
Foo <: Comparable<? super T>
( A <: B means A is a subtype of B)
If Foo is Comparable at all, it almost certainly implements Comparable<Foo> [2]
=>
Comparable<Foo> <: Comparable<? super T>
=>
T <: Foo
Without further information, inference chooses T=Foo.
Therefore from caller's POV, the two versions are not really different.
Inside method body, the 2nd version does not have access to type parameter X, which is a synthetic one introduced in compilation phase. This means you can only read from data. Things like
X x = data.get(0);
data.set(1, x);
are impossible in version#2; No such problem in version #1 with T.
However we can forward #2 to #1
<T1> method1(List<T1> data){ data.set(...); }
<T2> method2(List<?...> data)
{
method1(data);
}
(they must have difference method names; overloading not allowed since java7)
This is because for the compiler, type of data is really List<X> (it knows the secrete X), so there is no problem calling method1(data) after inferring that T1=X
[1] JLS3, 5.1.10 Capture Conversion
[2] According to the javadoc of Comparable, This interface imposes a total ordering on the objects of each class that implements it. That means if Foo implements Comparable<W>, W must be Foo or a super type of Foo. It is quite improbably for a subclass implementation to define a total order among objects of a super class. So W most definitely should be Foo. Otherwise funny things would happen. The notorious example is 'Timestamp', its javadoc (now) explains why it can't be compared with its supertype Date
The first method expects a list of elements which can be compared against their own class or a supertype of it. Say, real numbers can be compared to any kind of numbers:
class Real extends Number implements Comparable<Number> {
public int compareTo(Number o) ...
}
A bit more restrictive, but still acceptable for your first method is the following:
class Real extends Number implements Comparable<Real> {
public int compareTo(Real o) ...
}
But the second method is actually not very different from this version:
public static int methodY(List<? extends Comparable<?>> data) ...
That is to say, you can replace T with an unnamed wildcard ? because it is used only once in the method signature. It does not use concepts like the same class or an object's own class, etc.