Java泛型和无穷大(可比)

Java泛型和无穷大(可比),java,generics,comparable,infinity,Java,Generics,Comparable,Infinity,使用Integer类型,可以执行以下操作: int lowest = Integer.MIN_VALUE; 如果我使用泛型,我能做什么 K lowest = <...>; 我被困在第一步。我唯一能做的就是将节点的键设置为当前的最小值。我不确定这是否足够。嗯,这不取决于K是什么类型吗 泛型的要点是K可以是任何类型(或某一类型的任何子类);为了能够调用K上的方法或访问它的属性,您需要使用通配符限制它的类型边界。这没有任何意义 考虑到此时您不知道K是什么(即,您一般地实现它…duh!)

使用Integer类型,可以执行以下操作:

int lowest = Integer.MIN_VALUE;
如果我使用泛型,我能做什么

K lowest = <...>;

我被困在第一步。我唯一能做的就是将节点的键设置为当前的最小值。我不确定这是否足够。

嗯,这不取决于K是什么类型吗


泛型的要点是K可以是任何类型(或某一类型的任何子类);为了能够调用K上的方法或访问它的属性,您需要使用通配符限制它的类型边界。

这没有任何意义

考虑到此时您不知道K是什么(即,您一般地实现它…duh!),您不能为它指定最小/最大界限

在K可能是int、long、string或object的情况下,您无法明智地猜测使用

Integer.MIN_值“”或NULL


我想你要找的是一个K.MIN_值,它是最终的类型,但并不存在。

对于所有可比较的类型,都没有
MIN_值
MAX_值
的通用形式


考虑一个实现comparable的
Time
类。时间没有最大值,即使它是可比较的。

仅仅因为对象是可比较的,并不意味着它必须有最小值。int的最小值为-(2^(31))的原因是符号需要1位,因此2^31是可以存储的最大(或最小)整数。对于像字符串这样的东西,它没有任何意义,因为没有可能的最大/最小字符串,它是内存限制的。

您可能必须创建一个接口“IInfinity”,并让K扩展IInfinity,IInfinity有一个方法“getInfinityValue()”,然后包装/扩展Integer、Double、BigDecimal,在实现IInfinity的类中。。。啊

基本上,您希望任何类型的K都实现一些静态函数,比如最低和最高函数,它们遵循标准的数学属性


我假设,为了使这种最低(或最高)的感觉可用,您希望任何可比较的对象都有这些方法。(或静态字段)。如果您只对自己的自定义对象感兴趣,那么实现这一点的方法是让所有内容都从抽象数据类型继承,该抽象数据类型为MINVALUE和MAX_VALUE声明静态字段,然后您的类型变量将是。如果其他类需要此功能,则需要创建某种外部hashmap,用于跟踪不同类的这些属性(但这会变得非常难看)

我正在尝试想象什么场景需要此类行为。这是我能想到的最好的

警告:此代码很危险。请原谅我张贴了这样一个令人憎恶的帖子。这只是一个概念的证明

public class Lowest<K> implements Comparable<K> {
    public int compareTo(K other) {
        return -1;
    }
}
公共类{
公共整数比较(K其他){
返回-1;
}
}
然后

public class Test {
    public <K extends Comparable<K>> K findMaximum(List<K> values) throws Exception {
        K lowest = (K) new Lowest<K>(); /// XXX DANGER! Losing compile-time safety!!!

        K maximum = lowest;
        for (K value : values) {
            if (maximum.compareTo(value) < 0) {
                maximum = value;
            }
        }

        if (maximum == lowest) {
            throw new Exception("Could not find a maximum value");
        } else {
            return maximum;
        }
    }
}
公共类测试{
公共K findMaximum(列表值)引发异常{
K loost=(K)new loost();///XXX危险!正在失去编译时安全性!!!
K最大值=最低值;
对于(K值:值){
if(最大比较值)<0){
最大值=最大值;
}
}
如果(最大值==最低值){
抛出新异常(“找不到最大值”);
}否则{
返回最大值;
}
}
}

考虑不要使
K
成为泛型,而是使用一个包装基本包装器(双包装器!)的接口

import java.util.HashMap;
公共类NodeWrapper实现了可比较的{
private static HashMap minVals=new HashMap();
私人K值;
私有节点包装器(){
超级();
}
公共节点包装器(K值,类clazz){
超级();
这个值=值;
if(minVals.get(clazz)==null){
minVals.put(clazz,newnodewrapper());
}
}
公共K getValue(){
返回值;
}
公共静态节点包装器getMinValue(类clazz){
返回minVals.get(clazz);
}
公共无效设置值(K值){
这个值=值;
}
@凌驾
公共整数比较(nodeo){
NodeWrapper min=minVals.get(this.getClass());
if(this==min&&o==min){
返回0;
}else if(this==min){
返回-1;
}如果(o==最小值),则为else{
返回1;
}否则{
返回此.value.compareTo(o.value);
}
}
}
简单地说,其思想是每当实例化一个新类时,都会创建一个最小值并将其放入一个静态hashmap中,该静态hashmap存储每个类的最小值。(事实上,这些值根本不是什么,只是一个sentinel对象,但由于我们将使用对象相等性来确定某个值是否为最小值,这一点都没有问题。)所需要的是,包装对象通常与自身的其他实例相比较

一个缺点是调用
getMinValue
时会出现编译器警告,因为返回类型没有通用信息。也许有一种更优雅的方式,但我现在想不起来


总的来说,这个总体想法可能相当不错。然而,我要强调的是:如果你尝试任何多态性或任何相互比较的类的混合,这将是绝对失败的<同一棵树中的code>Longs和
Integer
s将彻底摧毁您。

er。。。又是什么问题


与all一样,允许您使用集合中对象的实例来创建它。

您可以创建一个包装类,为所有类型“添加”最小值和最大值。它只有两个表示最小值和最大值的静态实例,然后其他实例包装某种类型的其他值。当我们进行比较时,我们检查其中一项是最小值还是最大值,并返回正确的结果;和
public class Test {
    public <K extends Comparable<K>> K findMaximum(List<K> values) throws Exception {
        K lowest = (K) new Lowest<K>(); /// XXX DANGER! Losing compile-time safety!!!

        K maximum = lowest;
        for (K value : values) {
            if (maximum.compareTo(value) < 0) {
                maximum = value;
            }
        }

        if (maximum == lowest) {
            throw new Exception("Could not find a maximum value");
        } else {
            return maximum;
        }
    }
}
import java.util.HashMap;


public class NodeWrapper<K extends Comparable<K>> implements Comparable<NodeWrapper<K>> {

    private static HashMap<Class, NodeWrapper> minVals = new HashMap<Class, NodeWrapper>();

    private K value;

    private NodeWrapper() {
        super();
    }

    public NodeWrapper(K value, Class<K> clazz) {
        super();
        this.value = value;

        if (minVals.get(clazz)==null) {
            minVals.put(clazz, new NodeWrapper<K>());
        }
    }

    public K getValue() {
        return value;
    }

    public static NodeWrapper getMinValue(Class clazz){
        return minVals.get(clazz);
    }

    public void setValue(K value) {
        this.value = value;
    }

    @Override
    public int compareTo(NodeWrapper<K> o) {
        NodeWrapper min = minVals.get(this.getClass());
        if (this==min && o==min)  {
            return 0;
        } else if (this==min){
            return -1;
        } else if (o==min){
            return 1;
        } else {
            return this.value.compareTo(o.value);
        }
    }

}
class Extended<T extends Comparable<? super T>> implements Comparable<Extended<T>> {
    private Extended() { }

    private static Extended min = new Extended();
    private static Extended max = new Extended();

    @SuppressWarnings("unchecked")
    public static <T extends Comparable<? super T>> Extended<T> getMin() {
        return (Extended<T>)min;
    }
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<? super T>> Extended<T> getMax() {
        return (Extended<T>)max;
    }

    public T value;

    public Extended(T x) { value = x; }

    public int compareTo(Extended<T> other) {
        if (this == other) return 0;
        else if (this == min || other == max) return -1;
        else if (this == max || other == min) return 1;
        else return this.value.compareTo(other.value);
    }
}