Frage

Mit dem Typ Integer Sie können dies tun:

int lowest = Integer.MIN_VALUE;

Was kann ich tun, wenn ich Generika verwenden?

K lowest = <...>;

Ich brauche das, um etwas ähnlich eine Priorityqueue zu implementieren. Ich habe Zugang zu einem Knoten I aus der Warteschlange entfernt werden soll, aber es ist nicht die min.

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

Ich bin auf der ersten Stufe stecken. Das einzige, was ich tun kann, ist, den Schlüssel des Knotens auf den aktuellen min eingestellt. Nicht sicher, es ist genug.

War es hilfreich?

Lösung

Das macht keinen Sinn ...

Da Sie nicht wissen, was K an diesem Punkt ist, (das heißt Sie es sind die Umsetzung generisch ... duh!) Sie keine min / max gebunden dafür angeben können.

in einem Fall, in dem K a int, long, string oder ein Objekt sein könnte, könnte man nicht sinnvoll nutzen erraten

Integer.MIN_VALUE "" OR NULL.

Ich denke, was Sie suchen eine K.MIN_VALUE_OF_EVENTUAL_TYPE ist aber, dass nicht existiert.

Andere Tipps

Es gibt keine generische Form von MIN_VALUE oder MAX_VALUE für alle vergleichbaren Typen.

Denken Sie an eine Time Klasse, die vergleichbar implementiert. Es gibt keine MAX_VALUE für Zeit, obwohl es vergleichbar ist.

Ich versuche, sich vorzustellen, was Szenario ein solches Verhalten erfordern würde. Das ist das Beste, was ich mit oben kommen kann ...

ACHTUNG: Dieser Code ist gefährlich. Bitte sei mir gnädig für eine solche Gräuel veröffentlichen. Es ist nur ein Proof of Concept.

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

Und dann ...

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

Sie können eine Wrapper-Klasse machen, dass „fügt“ einen Minimal- und Maximalwert für alle Typen. Es hat nur zwei statische Instanzen, die minimale und maximale darstellen, und dann anderen Fällen einen anderen Wert von irgendeiner Art wickeln. Wenn wir einen Vergleich zu tun, überprüfen wir, ob eines der Dinge, das Minimum oder Maximum ist, und das richtige Ergebnis zurück; und sonst tun wir nur den gleichen Vergleich wie der zugrunde liegende Typ. So etwas wie folgt aus:

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

äh ... was ist das Problem wieder?

Priorityqueue, wie alle < a href = "http://java.sun.com/javase/6/docs/api/java/util/Collection.html#remove(java.lang.Object)" rel = "nofollow noreferrer"> Sammlungen , können Sie eine Instanz eines Objekts auf entfernen es aus der Sammlung.

Uh bedeutet dies nicht davon abhängen, welche Art K ist?

Der Punkt von Generics ist, dass K ein beliebiger Typ sein kann (oder eine Unterklasse eines bestimmten Typs); um Methoden aufzurufen auf K oder Zugriffseigenschaften davon zu können, müssen Sie es eingeben Grenzen mit Wildcards beschränken.

, nur weil ein Objekt eine vergleichbar ist, bedeutet nicht, dass es einen Minimalwert haben muss. Der Grund int hat einen Minimalwert von - (2 ^ (31)) ist, weil Sie für ein Zeichen 1 Bit benötigen, also 2 ^ 31 ist die größte (oder kleinste) möglich Ganzzahl, die gespeichert werden kann. Für Dinge wie string, macht es keinen Sinn machen, da es keine größte / kleinste mögliche Zeichenfolge ist es Speicher gebunden ist.

Sie müssen möglicherweise eine Schnittstelle „IInfinity“, erstellen und K erweitert IInfinity und IInfinity ein Verfahren „getInfinityValue ()“ haben, und dann wickeln / verlängern Integer, Double, BigDecimal, etc. in einer Klasse, die IInfinity implementiert ... und igitt!

Im Grunde wollen Sie jede Art K einige statischen Funktionen sagen niedrigsten zu implementieren und höchst die gehorchen die üblichen mathematischen Eigenschaften.

Ich gehe davon aus, dass für dieses Gefühl der niedrigsten (oder höchsten) einsetzbar sein würden Sie jede vergleichbare Aufgabe, diese Methoden zu haben. (Oder statische Felder). Wenn Sie daran interessiert sind nur in Ihrer eigenen benutzerdefinierten Objekte sind, auf die Art und Weise dies zu tun wäre alles von einem abstrakten Datentyp erben zu haben, die für MINVALUE und MAX_VALUE statische Felder deklariert und dann würde Ihre Art varaibles sein. Wenn Sie diese Funktionalität für andere Klassen benötigen, müssen Sie irgendeine Art von externen hashmap cre4ate, die diese Eigenschaften für verschiedene Klassen Spuren (aber das würde sich ziemlich hässlich)

Betrachten Sie nicht eine generische machen K, sondern über eine Schnittstelle, die die primitiven Wrapper-Wraps (ein Doppel-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);
        }
    }

}

Kurz gesagt, ist die Idee, dass, wenn eine neue Klasse instanziiert wird, wird ein Minimalwert erstellt und in einen statischen hashmap, die die Mindestwerte für jede Klasse speichert. (In der Tat ist diese Werte gar nichts, nur ein Sentinel-Objekt, aber da wir Objekt Gleichheit verwenden, um festzustellen, ob etwas ist der Minimalwert, ist dies kein Problem.) Alles, was notwendig ist, dass das umhüllte Objekt vergleichbar sein in den anderen Fällen von sich im allgemeinen.

Ein Nachteil ist, dass, wenn Sie anrufen getMinValue Sie Compiler-Warnungen haben werden, da der Rückgabetyp keine allgemeinen Informationen hat. Es kann ein eleganter Weg, um dieses, aber ich kann es jetzt nicht denken.

Diese allgemeine Idee könnte insgesamt eher nett sein. Allerdings soll ich wirklich betonen: Das wird absolut brechen, wenn Sie es mit jedem Polymorphismus oder jede Vermischung von miteinander vergleichbaren Klassen versuchen. Longs und Integers im gleichen Baum werden Sie völlig zerstören.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top