(If this is a duplicate please point me to the right answer! I searched and read several (>5) related questions but none seemed on the mark. Also looked at the Generics FAQ and other sources...)
It is apparently proper practice that when a collection class takes a comparator it should have the type Comparator<? super T>
for your parameterized type T
. And you can see that lots of places, e.g., TreeMap
. Okay.
My problem is working with Comparator.naturalOrder()
which is parameterized on T extends Comparable<? super T>
but returns a Comparator<T>
. I'm trying to have a field in my collection class that holds either the user-specified comparator or the Comparator.naturalOrder
comparator.
I can't get it to work. My questions, all related, are:
Comparator.naturalOrder
properly used?
naturalOrder
comparator?T
not T implements Comparable<? super T>
, so that's the design pattern chosen, how is naturalOrder
useful since it requires the latter bounded wildcard, not the unconstrained type parameter?Thanks!
Here follows the actual examples with compiler errors:
So: If I have code like this in some class where T has no bounds (as in all existing collection classes):
class Foo<T> {
private Comparator<? super T> comparator;
public void someMethod(Comparator<? super T> comparator)
{
this.comparator = comparator; // no compile error
this.comparator = Comparator.naturalOrder(); // incompatible types
}
}
with this error:
Error:(331, 50) java: incompatible types: inferred type does not conform to upper bound(s)
inferred: T
upper bound(s): java.lang.Comparable<? super T>
So if I decide to forgo the advantages of ? super T
then I have:
class Foo<T> {
private Comparator<T> comparator;
public void someMethod(ComparatorT> comparator)
{
this.comparator = comparator; // no compile error
this.comparator = Comparator.naturalOrder(); // incompatible types
}
}
where I have
Error:(nnn, 50) java: incompatible types: inference variable T has incompatible bounds
equality constraints: T
upper bounds: java.lang.Comparable<? super T>
The naturalOrder() method of Comparator Interface in Java returns a comparator that use to compare Comparable objects in natural order. The returned comparator by this method is serializable and throws NullPointerException when comparing null.
comparator,” Java Comparator compares two Java objects in a “compare(Object 01, Object 02)” format. Using configurable methods, Java Comparator can compare objects to return an integer based on a positive, equal or negative comparison.
It returns a positive value if obj1 is greater than obj2. Otherwise, a negative value is returned. By overriding compare( ), you can alter the way that objects are ordered. For example, to sort in a reverse order, you can create a comparator that reverses the outcome of a comparison.
Java Comparator interface is used to order the objects of a user-defined class. This interface is found in java. util package and contains 2 methods compare(Object obj1,Object obj2) and equals(Object element).
This compiles:
import java.util.*;
class Foo<T extends Comparable<? super T>> {
private Comparator<T> comparator;
public void someMethod(Comparator<T> comparator)
{
this.comparator = comparator; // no compile error
this.comparator = Comparator.<T>naturalOrder(); // <T> is optional, compiler can infer
}
}
The simplest way to think about it is this: you are trying to use type T with the Comparator interface, which imposes certain requirements on it (in particular it has that fancy recursive requirement that T must implement Comparable interface). You do not impose such requirement when genericising (?) your class, so compiler is not happy. Your requirements on T must be as strong as the class that you are using it with.
You are confused about what natural ordering method does. It just takes a class which implements Comparable and creates the default Comparator for it. No way around it -- you can't create a Comparator for something that is not Comparable.
You want TreeMap to require Comparable, but you can't, because it is a valid case to use something that is not comparable, as long as you have provided a Comparator. So TreeMap ends up not enforcing Comparable and just casts explicitly at runtime (and throws an exception).
I guess you have to implement Comparable to use Comparator.naturalOrder() in your class Foo in your example. You must have a method compareTo(Object o), that method is the one that implements the natural order so you don't need to store it in a variable.
I think you can use comparators in a class that doesn't implements the comparable interface at least in Java 8, so they don't implements compareTo(Object o) but you have to implement this
@FunctionalInterface
public interface Comparator<T>
This is from the Java 8 API
A comparison function, which imposes a total ordering on some collection of objects. Comparators can be passed to a sort method (such as Collections.sort or Arrays.sort) to allow precise control over the sort order. Comparators can also be used to control the order of certain data structures (such as sorted sets or sorted maps), or to provide an ordering for collections of objects that don't have a natural ordering.
A way of implementing and initialising it:
private Comparator<Operario> ComparatorOperario =
(o, p)-> o.getNombre().compareTo(p.getNombre());
then you can have getters and setters for this variable so you can change the way of ordering
note that the class Operario
doesn't implements Comparable
, it uses a Comparator<Operario>
that compares 2 attributes from the class Operario, in this case two Strings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With