Java 泛型和 Infinity(可比较)

发布于 2024-07-17 13:02:33 字数 409 浏览 14 评论 0原文

使用 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.

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

With the type Integer you can do this:

int lowest = Integer.MIN_VALUE;

What can I do if I use generics?

K lowest = <...>;

I need this in order to implement something similar to a PriorityQueue.
I have access to a node I want to remove from the queue, but it is not the min.

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

I am stuck on the first step. The only thing I can do is set the key of the node to the current min. Not sure it is enough.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

别闹i 2024-07-24 13:02:34

考虑不要使 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 时,您将收到编译器警告,因为返回类型没有通用信息。 可能有一种更优雅的方法来解决这个问题,但我现在想不到。

总体而言,这个总体想法可能相当不错。 然而,我真的应该强调:如果您尝试使用任何多态性或任何相互可比较的类的混合,这绝对会失败。 同一棵树中的LongInteger将彻底摧毁你。

Consider not making K a generic, but using an interface that wraps the primitive wrapper (a double wrapper!).

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

}

Briefly, the idea is that whenever a new class is instantiated, a minimum value is created and put into a static hashmap that stores the minimum values for each class. (In fact, these values are NOTHING at all, just a sentinel object, but since we will use object equality to determine if something is the min value, this is no problem at all.) All that's necessary is that the wrapped object be comparable to other instances of itself in general.

One drawback is that when you call getMinValue you will have compiler warnings, since the return type will have no generic information. There may be a more elegant way around this, but I can't think of it right now.

This general idea might be rather nice overall. However, I should really stress: this will absolutely break if you try it with any polymorphism or any mixing of mutually comparable classes. Longs and Integers in the same tree will completely destroy you.

和影子一齐双人舞 2024-07-24 13:02:34

呃……又出什么问题了?

PriorityQueue,像所有集合,允许您使用对象的实例 将其从集合中删除

er... what's the problem again?

PriorityQueue, like all Collections, allows you to use an instance of an object to remove it from the collection.

℡Ms空城旧梦 2024-07-24 13:02:34

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

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

Uh doesn't this depend on what type K is?

The point of Generics is that K can be any type (or any subclass of a certain type); in order to be able to call methods on K or access properties of it, you need to restrict it's type bounds with wildcards.

风尘浪孓 2024-07-24 13:02:34

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

just because an object is a comparable does not mean it has to have a minimum value. The reason int has a min value of -(2^(31)) is because you need 1 bit for a sign, so 2^31 is the largest (or smallest) possible integer that can be stored. For things like string, it does not make any sense since there is no largest/smallest possible string, it is memory bound.

倾城泪 2024-07-24 13:02:34

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

You might have to create an interface "IInfinity", and have K extends IInfinity, and IInfinity to have a method "getInfinityValue()", and then wrap/extend Integer, Double, BigDecimal, etc in a class that implements IInfinity ... and ugh!

我三岁 2024-07-24 13:02:34

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

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

Basically you want any type K to implement some static functions say lowest and highest which obey the standard mathematical properties.

I assume that for this sense of lowest (or highest) to be usable you would want any Comparable object to have these methods. (or static fields). If you are only interested in your own custom objects, the way to do this would be to have everything inherit from an abstract data type which declared static fields for MINVALUE and MAX_VALUE and then your type varaibles would be . If you need this functionality for other classes you will need to cre4ate some sort of external hashmap which tracks these properties for different classes (but that would get pretty ugly)

霞映澄塘 2024-07-24 13:02:33

对于所有 Comparable 类型,没有通用形式的 MIN_VALUEMAX_VALUE

考虑一个实现可比较的 Time 类。 尽管 Time 是 Comparable,但它没有 MAX_VALUE

There is no generic form of MIN_VALUE or MAX_VALUE for all Comparable types.

Think about a Time class that implements comparable. There is no MAX_VALUE for Time even though it is Comparable.

云仙小弟 2024-07-24 13:02:33

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

警告:此代码很危险。 请怜悯我发布如此令人厌恶的内容。 这只是一个概念证明。

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

I am trying to imagine what scenario would require such behavior. This is the best I can come up with...

WARNING: This code is dangerous. Please be merciful to me for posting such an abomination. It is only a proof of concept.

public class Lowest<K> implements Comparable<K> {
    public int compareTo(K other) {
        return -1;
    }
}

And then...

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;
        }
    }
}
夜未央樱花落 2024-07-24 13:02:33

这没有任何意义...

鉴于您当时不知道 K 是什么,(即您一般地实现它...废话!)您无法为其指定最小/最大界限。

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

Integer.MIN_VALUE、"" OR NULL。

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

This doesn't make any sense...

Given that you don't know what K is at that point, (i.e. You're implementing it generically... duh!) you can't specify a min/max bound for it.

in a case where K could be a int, long, string OR object, you couldn't sensibly guess to use

Integer.MIN_VALUE, "" OR NULL.

I guess what you're looking for is a K.MIN_VALUE_OF_EVENTUAL_TYPE but that doesn't exist.

再浓的妆也掩不了殇 2024-07-24 13:02:33

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

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

You can make a wrapper class that "adds" a minimum and maximum value to all types. It just has two static instances that represent minimum and maximum, and then other instances wrap some other value of some type. When we do a comparison, we check if one of the things is the minimum or maximum, and return the proper result; and otherwise we just do the same comparison as the underlying type. Something like this:

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文