6

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

int lowest = Integer.MIN_VALUE;

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

K lowest = <...>;

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

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

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

4

10 回答 10

5

所有 Comparable 类型都没有通用MIN_VALUE形式MAX_VALUE

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

于 2009-04-29T18:15:50.683 回答
5

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

警告:此代码很危险。请原谅我发布如此可憎的内容。这只是一个概念证明。

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;
        }
    }
}
于 2009-04-29T18:33:32.013 回答
4

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

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);
    }
}
于 2009-04-29T21:41:43.107 回答
4

这没有任何意义...

鉴于您当时不知道 K 是什么,(即您正在通用地实现它......呃!)您不能为它指定最小/最大界限。

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

整数.MIN_VALUE,“”或 NULL。

我猜您正在寻找的是 K.MIN_VALUE_OF_EVENTUAL_TYPE 但它不存在。

于 2009-04-29T18:15:41.557 回答
2

考虑不要制作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);
        }
    }

}

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

一个缺点是,当您调用时,getMinValue您会收到编译器警告,因为返回类型将没有通用信息。可能有一个更优雅的方法来解决这个问题,但我现在想不出。

总体而言,这个总体思路可能相当不错。但是,我真的应该强调:如果您尝试使用任何多态性或任何相互可比的类的混合,这绝对会失败。 Longs 和Integers 在同一棵树上会彻底摧毁你。

于 2009-04-29T20:08:28.790 回答
2

呃……又是什么问题?

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

于 2009-04-29T20:47:29.460 回答
1

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

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

于 2009-04-29T18:05:33.857 回答
1

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

于 2009-04-29T18:16:24.767 回答
1

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

于 2009-04-29T18:16:32.957 回答
1

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

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

于 2009-04-29T18:17:07.107 回答