java.util.Comparator.naturalOrder采用<t extends =“”可比较<?=“”super =“”t =“”>&gt;并返回比较器<t> - 为什么?</t> </t>

时间:2014-07-04 00:55:02

标签: java generics java-8 comparator bounded-wildcard

(如果这是重复的,请指出正确的答案!我搜索并阅读了几个(&gt; 5)相关问题,但似乎没有出现在标记上。还查看了泛型常见问题和其他来源......)< / p>

当一个集合类采用比较器时,它应该具有参数化类型Comparator<? super T>的类型T,这显然是正确的做法。你可以看到很多地方,例如TreeMap。好。

我的问题是使用在T extends Comparable<? super T>上参数化的Comparator.naturalOrder(),但返回Comparator<T>。我正在尝试在我的集合类中有一个字段,它包含用户指定的比较器或Comparator.naturalOrder比较器。

我无法让它发挥作用。我的所有相关问题都是:

  1. 如何正确使用Comparator.naturalOrder
    • 我可以做我想要的东西吗?我有一个存储用户提供的比较器或naturalOrder比较器的字段?
  2. 鉴于大多数集合类(在框架中)都是在T而不是T implements Comparable<? super T>上参数化的,所以选择的是设计模式,naturalOrder如何有用,因为它需要后者有界通配符,而不是无约束的类型参数?
  3. 谢谢!

    下面是编译器错误的实际示例:

    所以:如果我在某些类中有这样的代码,其中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>
    

2 个答案:

答案 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个属性,在本例中为两个字符串。

相关问题