Java Collection compare generic class that extends interface that extends comparable - java

I have this interface
public interface IDataPoint<T> extends Comparable<T> {
public T getValue();
}
and this implementation...
public class IntegerDataPoint implements IDataPoint<Integer> {
// ... some code omitted for this example
public int compareTo(Integer another) {
// ... some code
}
}
and another class...
public class HeatMap<X extends IDataPoint<?> {
private List<X> xPoints;
}
Now I would like to use Collections.max (and similar) on the xPoints list, but that does not work, probably because I got my generics all messed up.
Any suggestions how this could be solved (without a Comparator)?
Collections.max(xPoints);
gives me this error:
Bound mismatch: The generic method max(Collection<? extends T>) of type Collections is not applicable for the arguments (List<X>). The inferred type X is not a valid substitute for the bounded parameter <T extends Object & Comparable<? super T>>

The problem is that Collections.max(Collection<? extends T>) wants the T's to be comparable to themselves not some other type.
In your case IntegerDataPoint is comparable to Integer, but not IntegerDataPoint
You cannot easily fix this because IntegerDataPoint is not allowed to implement Comparable<Integer> and Comparable<IntegerDataPoint> at the same time.

Related

Additional type bounds in constructor

Say I have a class like this:
class OrderedFoo<T> {
public OrderedFoo(Comparator<? super T> comparator) {
//Do something
}
}
I could use this for non-comparable objects as the type parameter is not required to implement Comparable.
I could also use this for comparable objects, making use of Comparator#naturalOrder.
Example:
OrderedFoo<Watchable> nonComparable = new OrderedFoo<>((a, b) -> foo());
OrderedFoo<String> comparable = new OrderedFoo<>(Comparator.naturalOrder());
However, it gets somewhat tedious to have to specify a default comparator for comparable types. Is it possible to write a constructor with type parameters that will only accept a comparable type?
//Like this
public <???> OrderedFoo() {
this(Comparator.naturalOrder());
}
I tried <T extends Comparable<? super T>> but I get
(java.util.Comparator<? super T>)
in OrderedFoo cannot be applied to
(java.util.Comparator<T>)
Is this possible with a constructor?
You can't do this directly with a constructor, because that constructor has to be applicable to all types; but you want it only to work for Comparable types.
Use a static factory method with a suitably-constrained type variable:
public static <T extends Comparable<T>> OrderedFoo<T> naturalOrder() {
return new OrderedFoo<>(Comparator.naturalOrdering());
}

generics and wild cards

I'm trying to write
public static Comparable<? extends Comparable> getMax (ArrayList <? extends Comparable> list)
and I recieve an exception
Comparable is a raw type. References to generic type Comparable should be
parameterized
what can I do? I want recieve a collection and return an varaiable who implement the interface
If you want to find the max value in a list, why do you return a Comparable? Returning T where T is the type of object that the list stores is much better.
In addition, wildcards should not be used here. If you write your method like this:
public static Comparable<? extends Comparable> getMax (ArrayList <? extends Comparable> list)
then the client code can pass ArrayList<Integer> and you can return a String which makes no sense at all.
To avoid that kind of situation, I suggest you to use a generic type T
public static <T extends Comparable<T>> T getMax (ArrayList<T> list) {
return list.stream().max(Comparable::compareTo).orElse(null);
}

Java Comparable for Generic Types

When trying to compare a generic type in the form
Class<T> implements Comparable<T> {
public int compareTo(T other){
this.T < other
}
}
does not work for me but when using
Class<T extends Comparable<T>>{
T.compareTo(other.T)
}
does work. I have been unable to deciper why I can't compare T directly using the first example
In your first example:
class Foo<T> implements Comparable<T> {
you're saying that Foo objects are comparable. In your second example:
class Foo<T extends Comparable<T>>{
you're saying that whatever T, is, it's comparable.
Then, in the body of your code, you try to compare things of type T -- in the first case, you have no guarantee that they're comparable, in the second, you do.
I hope these two exmaples will cast some light on your problem:
class Foo<T> implements Comparable<T> {
#Override
public int compareTo(T o) {
// We don't know anything about T
return hashCode() - o.hashCode();
}
}
class Boo<T extends Comparable<? super T>> implements Comparable<T> {
private T instance;
#Override
public int compareTo(T o) {
// We know that T implements Comparable<? super T>
return instance.compareTo(o);
}
}
In first case with Foo, you don't know anything about type T, so you can't do much in your compareTo() method.
However, in Boo, T is required to implement Comparable<? super T> (if you don't know what wildcards are, just think there is simply Comparable<T>), so you can call t.compareTo(anotherT). More about bounded type parameters.
EDIT: (wildard explained)
Consider following code:
class Car implements Comparable<Car> { ... }
class SportCar extends Car { ... }
Now call sportCar1.compareTo(SportCar2) is perfectly legal. However, without the wildcard,
Bar<SportCar> is a cpompile error!
Why? Because SportCar doesn't implement Comparable<SportCar>. And you require T to implement Comparable<T>, and in this case T is SportCar.
But SportCar implements Comparable<Car> and Car is a supertype of SportCar. So you want to say something like "T can be compared to T or any supertype of T" (like in this case SportCar can be compared to any Car).
And that what the wildcard is for (among many other things). Hope this helps.

I want limit type T that is a class which implements the Comparable<T> interface in a generic class

I defined a generic class A<T> in Java, but I want to limit the type T such that it is a class which implements the Comparable<T> interface. What should i do?
I think you just want:
class A<T extends Comparable<T>>
{
}
Or possibly:
class A<T extends Comparable<? super T>>
{
}
The latter is slightly more flexible - it allows for things like:
class Foo implements Comparable<Object>
{
}
A<Foo> a = new A<Foo>();
That's fine if you just want A to be able to compare values of type T.
public class A<T extends Comparable<? super T>>{
...
}
this allows you to use subclasses of classes that implement comparable
You can put an upper bound on T:
public class A<T extends Comparable<T>> {
//...
}
Class A <T implements ComparableInterface>

Java interface extends Comparable

I want to have an interface A parameterised by T A<T>, and also want every class that implements it to also implement Comparable (with T and its subtypes). It would seem natural to write interface A<T> extends Comparable<? extends T>, but that doesn't work. How should I do it then?
When Comparable<? extends T> appears it means you have an instance of Comparable that can be compared to one (unknown) subtype of T, not that it can be compared to any subtype of T.
But you don't need that, because a Comparable<T> can compare itself to any subtype of T anyway, e.g. a Comparable<Number> can compare itself to a Comparable<Double>.
So try:
interface A<T> extends Comparable<T> {
// ...
}
or
interface A<T extends Comparable<T>> extends Comparable<A<T>> {
// ...
}
depending on whether you need to be able to compare instances of T in order to implement your compareTo method.
If you use comparable you do not need to specify the possibility for subtypes in the compare function, it is by nature possible to pass in any subtype of an object X into a method that declared a parameter of class X. See the code below for more information.
public interface Test<T> extends Comparable<T> {
}
class TestImpl implements Test<Number> {
#Override
public int compareTo(final Number other) {
return other.intValue() - 128;
}
}
class TestMain {
public static void main(final String[] args) {
TestImpl testImpl = new TestImpl();
testImpl.compareTo(Integer.MIN_VALUE);
}
}

Categories