Pergunta

Com o tipo Integer você pode fazer isso:

int lowest = Integer.MIN_VALUE;

O que posso fazer se eu usar os genéricos?

K lowest = <...>;

Eu preciso disso, a fim de implementar algo semelhante a um PriorityQueue. Eu tenho acesso a um nó que deseja remover da fila, mas não é o min.

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

Eu estou preso na primeira etapa. A única coisa que posso fazer é definir a chave do nó para o min atual. Não tenho certeza que é suficiente.

Foi útil?

Solução

Isto não faz qualquer sentido ...

Uma vez que você não sabe o que K é nesse ponto, (ou seja, você está implementando-o genericamente ... duh!), Você não pode especificar um min / max ligado para ele.

num caso em que K pode ser um int, long, string ou objeto, você não poderia de forma sensata acho que para uso

Integer.MIN_VALUE, "" ou nulo.

Eu acho que o que você está procurando um K.MIN_VALUE_OF_EVENTUAL_TYPE mas isso não existe.

Outras dicas

Não há forma genérica de MIN_VALUE ou MAX_VALUE para todos os tipos comparáveis.

Pense em uma classe Time que implementa comparáveis. Não há MAX_VALUE para o período, mesmo que é comparável.

Eu estou tentando imaginar o cenário exigiria tal comportamento. Este é o melhor que pode vir até com ...

AVISO: Este código é perigoso. Por favor, tem misericórdia de mim para postar tal abominação. É apenas uma prova de conceito.

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

E então ...

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

Você pode fazer uma classe wrapper que "acrescenta" um valor mínimo e máximo de todos os tipos. Ele só tem duas instâncias estáticos que representam o mínimo eo máximo, e depois outros casos envolvem algum outro valor de algum tipo. Quando fazemos uma comparação, vamos verificar se uma das coisas é o mínimo ou máximo, e retornar o resultado correto; e caso contrário, basta fazer a mesma comparação como o tipo subjacente. Algo parecido com isto:

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

er ... qual é o problema novamente?

PriorityQueue , como todos < a href = "http://java.sun.com/javase/6/docs/api/java/util/Collection.html#remove(java.lang.Object)" rel = "nofollow noreferrer"> Collections , permite que você use uma instância de um objeto para Remover -lo da coleção.

Uh não esta depender do tipo K é?

O ponto de Generics é que K pode ser de qualquer tipo (ou qualquer subclasse de um certo tipo); a fim de ser capaz de chamar métodos em K ou propriedades de acesso do mesmo, que você precisa para restringir o seu tipo limites com curingas.

só porque um objeto é um comparável não significa que tem que ter um valor mínimo. O int razão tem um valor min de - (2 ^ (31)) é porque você precisa de 1 bit por sinal, de modo 2 ^ 31 é o maior (ou menor) possível inteiro que pode ser armazenado. Para coisas como cordas, não faz qualquer sentido, pois não há maior / menor seqüência possível, é memória ligada.

Você pode ter que criar uma interface "IInfinity", e têm K estende IInfinity e IInfinity ter um método "getInfinityValue ()" e, em seguida, enrole / estender Integer, Double, BigDecimal, etc em uma classe que implementa IInfinity ... e ugh!

Basicamente você quer qualquer tipo K para implementar algumas funções estáticas dizer menor e maior que obedecer as propriedades matemáticas padrão.

Eu assumo que para este sentimento de menor (ou maior) para ser utilizável você iria querer qualquer objeto Comparável a ter estes métodos. (campos estáticos ou). Se você está interessado apenas em seus próprios objetos personalizados, a maneira de fazer isso seria ter tudo herdar de um tipo de dado abstrato que declarou campos estáticos para MINVALUE e MAX_VALUE e, em seguida, o seu tipo de varaibles seria. Se você precisar dessa funcionalidade para outras classes você precisará cre4ate algum tipo de hashmap externa que acompanha essas propriedades para diferentes classes (mas que iria ficar muito feio)

Considere não fazer K um genérico, mas usando uma interface que envolve o invólucro primitivo (um duplo invólucro!).

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

}

Em resumo, a idéia é que sempre que uma nova classe é instanciado, um valor mínimo é criado e colocado em um hashmap estática que armazena os valores mínimos para cada classe. (Na verdade, esses valores são nada, apenas um objeto sentinela, mas desde que usará a igualdade objeto para determinar se algo é o valor min, isso não é problema de todos.) Tudo que é necessário é que o objeto embrulhado ser comparável a outras instâncias de si mesmo em geral.

Uma desvantagem é que quando você chamar getMinValue você terá avisos do compilador, já que o tipo de retorno não terá informações genéricas. Pode haver uma maneira mais elegante de contornar isso, mas eu não posso pensar nisso agora.

Esta ideia geral pode ser bastante agradável em geral. No entanto, eu realmente deveria estresse: este será absolutamente quebrar se você experimentá-lo com qualquer polimorfismo ou qualquer mistura de classes mutuamente comparáveis. Longs e Integers na mesma árvore vai destruir completamente você.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top