(如果这是重复的,请指出正确的答案!我搜索并阅读了几个(&gt; 5)相关问题,但似乎没有出现在标记上。还查看了泛型常见问题和其他来源......)< / p>
当一个集合类采用比较器时,它应该具有参数化类型Comparator<? super T>
的类型T
,这显然是正确的做法。你可以看到很多地方,例如TreeMap
。好。
我的问题是使用在T extends Comparable<? super T>
上参数化的Comparator.naturalOrder()
,但返回Comparator<T>
。我正在尝试在我的集合类中有一个字段,它包含用户指定的比较器或Comparator.naturalOrder
比较器。
我无法让它发挥作用。我的所有相关问题都是:
Comparator.naturalOrder
?
naturalOrder
比较器的字段?T
而不是T implements Comparable<? super T>
上参数化的,所以选择的是设计模式,naturalOrder
如何有用,因为它需要后者有界通配符,而不是无约束的类型参数?谢谢!
下面是编译器错误的实际示例:
所以:如果我在某些类中有这样的代码,其中T没有边界(如在所有现有的集合类中):
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
}
}
出现此错误:
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>
因此,如果我决定放弃? super T
的优势,那么我有:
class Foo<T> {
private Comparator<T> comparator;
public void someMethod(ComparatorT> comparator)
{
this.comparator = comparator; // no compile error
this.comparator = Comparator.naturalOrder(); // incompatible types
}
}
我在哪里
Error:(nnn, 50) java: incompatible types: inference variable T has incompatible bounds
equality constraints: T
upper bounds: java.lang.Comparable<? super T>
答案 0 :(得分:6)
编译:
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
}
}
考虑它的最简单方法是:您正在尝试将类型T与Comparator接口一起使用,这对它施加了某些要求(特别是它具有T必须实现Comparable接口的那种花哨的递归要求)。在对类进行泛化(?)时不要强加这样的要求,因此编译器不满意。您对T的要求必须与您使用它的类一样强。
您对自然排序方法的作用感到困惑。它只需要一个实现Comparable的类,并为它创建默认的Comparator。没办法 - 你不能为不可比的东西创建一个比较器。
您希望TreeMap需要Comparable,但是您不能这样做,因为只要您提供了Comparator,使用不具有可比性的内容就是一个有效的案例。所以TreeMao最终没有强制执行Comparable,只是在运行时显式转换(并引发异常)。
答案 1 :(得分:2)
我猜你必须实现Comparable才能在你的例子中使用类Foo中的Comparator.naturalOrder()。 你必须有一个方法compareTo(Object o),该方法是实现自然顺序的方法,因此你不需要将它存储在变量中。
我认为你可以在一个至少在Java 8中没有实现类似接口的类中使用比较器,所以他们不会实现compareTo(Object o),但是你必须实现这个
@FunctionalInterface
public interface Comparator<T>
这是来自Java 8 API
比较函数,它对某些对象集合施加总排序。可以将比较器传递给排序方法(例如Collections.sort或Arrays.sort),以便精确控制排序顺序。比较器还可用于控制某些数据结构的顺序(例如有序集或有序映射),或者为不具有自然顺序的对象集合提供排序。
实现和初始化它的一种方式:
private Comparator<Operario> ComparatorOperario =
(o, p)-> o.getNombre().compareTo(p.getNombre());
然后你可以为这个变量设置getter和setter,这样你就可以改变排序方式了
请注意,课程Operario
并未实现Comparable
,它使用Comparator<Operario>
来比较Operario类中的2个属性,在本例中为两个字符串。