Java.util.Comparator.naturalOrder accepts <T extends Comparable <? super T >> and returns the Comparator <T> - why?

(If this is a duplicate, please indicate me the correct answer! I searched and read several (> 5) related questions, but none of them seemed to be in place. I also looked at frequently asked questions on generalizations and other sources ...)

Apparently, the good practice is that when a collection class accepts a comparator, it should be of type Comparator<? super T> Comparator<? super T> for your parameterized type T And you can see many places, for example TreeMap . Good.

My problem works with Comparator.naturalOrder() , which is parameterized to T extends Comparable<? super T> T extends Comparable<? super T> , but returns Comparator<T> . I am trying to have a field in my collection class that contains either a user-specified comparator or a comparator.naturalOrder comparator.

I can not make it work. My questions related to me:

  • How to use Comparator.naturalOrder correctly?
    • And can I do what I want, which has a field where I store either a user-supplied comparator or a naturalOrder comparator?
  • Given that most collection classes (in structure) are parameterized to T not T implements Comparable<? super T> T implements Comparable<? super T> , so the selected design pattern, how naturalOrder is useful, because it requires the last bounded pattern, and not an unlimited type parameter?

Thanks!

The following are examples with compiler errors:

So: if I have such code in some class where T has no boundaries (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 give up the benefits ? super T ? 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> 
+6
source share
2 answers

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 easiest way to think about it: you are trying to use a type T with a Comparator interface that imposes certain requirements on it (in particular, it has such a bizarre recursive requirement that T must implement the Comparable interface). You do not impose such a requirement when generating (?) Your class, so the compiler is not happy. Your requirements for T should be as strong as the class with which you use it.

You are embarrassed by what the natural ordering method does. It simply takes a class that implements Comparable and creates a default Comparator for it. In no case can you create a Comparator for something that is not comparable.

You want TreeMap to require Comparable, but you cannot, because it is a valid case to use something incomparable if you provided Comparator. Thus, TreeMao does not force the comparison and just throws explicitly at runtime (and throws an exception).

+6
source

I think you need to implement Comparable to use Comparator.naturalOrder () in your Foo class in your example. You should have a compareTo (Object o) method, this method is the one that implements the natural order, so you do not need to store it in a variable.

I think you can use comparators in a class that does not implement a comparable interface, at least in Java 8, so they do not implement compareTo (Object o), but you must implement this

 @FunctionalInterface public interface Comparator<T> 

This is from the Java 8 API

A comparison function that imposes full ordering on a set of objects. Comparators can be passed to a sorting method (e.g. Collections.sort or Arrays.sort) to provide precise control over the sorting order. Comparators can also be used to control the order of certain data structures (for example, sorted sets or sorted maps) or to organize collections of objects that do not have a natural order.

Method of implementation and initialization:

 private Comparator<Operario> ComparatorOperario = (o, p)-> o.getNombre().compareTo(p.getNombre()); 

then you can have getters and setters for this variable so that you can change the way you arrange

note that the Operario class Operario not implement Comparable , it uses the Comparator<Operario> , which compares 2 attributes from the Operario class, in this case two lines.

+2
source

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


All Articles