繁体   English   中英

Java泛型和无限(可比)

[英]Java Generics and Infinity (Comparable)

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

int lowest = Integer.MIN_VALUE;

如果我使用泛型,我该怎么办?

K lowest = <...>;

我需要这个来实现类似于PriorityQueue的东西。 我可以访问我想要从队列中删除的节点,但它不是min。

1. I need to make it the min by decreasing the key of that node,
2. And then remove the min.

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

这没有任何意义......

鉴于你不知道K在那一点上是什么,(即你一般都是在实现它......呃!)你不能指定它的最小/最大界限。

在K可以是int,long,string OR对象的情况下,你无法明智地猜测使用它

Integer.MIN_VALUE,“”OR NULL。

我猜你要找的是K.MIN_VALUE_OF_EVENTUAL_TYPE但是不存在。

对于所有可比较类型,没有通用形式的MIN_VALUEMAX_VALUE

想想实现可比较的Time类。 即使它是可比较的,时间也没有MAX_VALUE

我试图想象什么情况需要这样的行为。 这是我能想到的最好的......

警告:此代码很危险。 发表这样的憎恶,请怜悯我。 这只是一个概念证明。

public class Lowest<K> implements Comparable<K> {
    public int compareTo(K other) {
        return -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;
        }
    }
}

您可以创建一个包装类,为所有类型“添加”最小值和最大值。 它只有两个表示最小值和最大值的静态实例,然后其他实例包含某些类型的其他值。 当我们进行比较时,我们检查其中一个是最小值还是最大值,并返回正确的结果; 否则我们只是做与基础类型相同的比较。 像这样的东西:

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);
    }
}

呃......又是什么问题?

与所有集合一样PriorityQueue允许您使用对象的实例其从集合中删除

呃这不取决于K是什么类型的?

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

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

您可能必须创建一个接口“IInfinity”,并使K扩展IInfinity,并使IInfinity具有方法“getInfinityValue()”,然后在实现IInfinity的类中包装/扩展Integer,Double,BigDecimal等...呃!

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

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

考虑不要使K成为泛型,而是使用包装原始包装器的接口(双包装器!)。

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);
        }
    }

}

简而言之,这个想法是每当实例化一个新类时,就会创建一个最小值并将其放入一个静态hashmap中,该hashmap存储每个类的最小值。 (事实上​​,这些值根本就没有,只是一个标记对象,但由于我们将使用对象相等来确定某些东西是否为最小值,这根本不是问题。)所有必要的是包装对象是可比较的一般而言,对于其他自身的实例。

一个缺点是,当您调用getMinValue时,您将getMinValue编译器警告,因为返回类型将没有通用信息。 可能有更优雅的方式,但我现在想不到它。

总体思路可能相当不错。 但是,我应该强调:如果你尝试使用任何多态或任何相互比较的类混合,这绝对会破坏。 同一棵树中的Long s和Integer将完全摧毁你。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM