如何在Java中实现通用的`max(Comparable a,Comparable b)`函数?

时间:2011-06-23 10:03:40

标签: java generics comparable

我正在尝试编写一个通用的max函数,它需要两个Comparable s。

到目前为止我已经

public static <T extends Comparable<?>> T max(T a, T b) {
    if (a == null) {
        if (b == null) return a;
        else return b;
    }
    if (b == null)
        return a;
    return a.compareTo(b) > 0 ? a : b;
}

无法使用

进行编译
The method compareTo(capture#5-of ?) in the type Comparable<capture#5-of ?> is not applicable for the arguments (T)

我认为这是说?中的Comparable<?>可能被解释为参数a的一种类型,而参数b的另一种类型被解释为无法进行比较。< / p>

如何从这个洞中挖掘自己?

5 个答案:

答案 0 :(得分:28)

为了获得最佳效果,您应该使用public static <T extends Comparable<? super T>> T max(T a, T b)

<T extends Comparable<?>>的问题在于,这表示类型T与某种类型相当,但您不知道该类型是什么。当然,常识会要求实现Comparable的类应该能够至少与其自身相比(即能够与其自身类型的对象进行比较),但从技术上讲,没有什么能阻止A类实现{{1其中A和B彼此无关。 Comparable<B>解决了这个问题。

但这有一个微妙的问题。假设类X实现了<T extends Comparable<T>>,并且我有一个扩展X的类Y.所以类Y通过继承自动实现Comparable<X>。 Y类也不能实现Comparable<X>,因为类不能使用不同的类型参数实现两次接口。这不是一个真正的问题,因为Y的实例是X的实例,所以Y可以与Y的所有实例相比。但问题是你不能使用类型Y和你的Comparable<Y>函数,因为Y没有'实施<T extends Comparable<T>> T max(T a, T b)。界限太严格了。 Comparable<Y>解决了这个问题,因为T足以与某些超类型的T(包括所有T实例)相比较。回想一下规则PECS - producer <T extends Comparable<? super T>>,consumer extends - 在这种情况下,super是一个使用者(它接受一个要比较的对象),所以Comparable有意义

这是Java库中所有排序和排序函数使用的类型边界。

答案 1 :(得分:4)

您收到此错误,因为Comparable<?>基本上表示它与没有任何细节的内容相当。您应该编写Comparable<T>,因此编译器会知道类型T与其自身相当。

答案 2 :(得分:1)

从SO生成的相关链接回答我自己的问题 - 这似乎是Fun with Java generics的一个微妙的重复,虽然我想你不能责怪我没有找到它的标题!

最简单的解决方案似乎是

public static <T extends Comparable<T>> T max(T a, T b) {
    if (a == null) {
        if (b == null) return a;
        else return b;
    }
    if (b == null)
        return a;
    return a.compareTo(b) > 0 ? a : b;
}

答案 3 :(得分:1)

我为此编写了一个实用程序类。也许你觉得它很有用(图书馆是开源的):

http://softsmithy.sourceforge.net/lib/docs/api/org/softsmithy/lib/util/Comparables.html

主页:

http://www.softsmithy.org

下载:

http://sourceforge.net/projects/softsmithy/files/softsmithy/

的Maven:

<dependency>  
    <groupid>org.softsmithy.lib</groupid>  
    <artifactid>lib-core</artifactid>  
    <version>0.1</version>  
</dependency> 

答案 4 :(得分:0)

最好将已经实现的iso创建为拥有。参见Min / Max function with two Comparable。最简单的是org.apache.commons.lang.ObjectUtils

Comparable<C> a = ...;
Comparable<C> b = ...;
Comparable<C> min = ObjectUtils.min(a, b);