Domanda

Ricordo che eclipse e l'idea hanno questo modello per creare automaticamente l'hashCode di un oggetto in base ai suoi attributi.

Una delle strategie se si usano un numero e una stringa è qualcosa del genere.

  return stringValue.hashCode() + intValue * 32;

Ooor qualcosa del genere.

Non ho né eclissi né idea a portata di mano e vorrei creare tale funzione.

Modifica

Sulla base delle risposte che creo questa mini-classe

    class StringInt {
        private final String s;
        private final int i;

        static StringInt valueOf( String string , int value ) {
            return new StringInt( string, value );
        }
        private StringInt( String string, int value ) {
            this.s = string;
            this.i = value;
        }
        public boolean equals( Object o ) {
            if( o != null && o instanceof StringInt ){
                StringInt other = ( StringInt ) o;
                return this.s == other.s && this.i == other.i;
            }

            return false;
        }
        public int hashCode() {
            return s != null ? s.hashCode() * 37 + i : i;
        }
    }

Questa classe deve essere usata come chiave per una grande mappa di memoria (elementi > 10k) Non voglio iterarli ogni volta per scoprire se String e int sono uguali.

Grazie.

ps .. mmh probabilmente dovrebbe essere un nome StringIntKey.

È stato utile?

Soluzione

Usa l'HashcodeBuilder di Apache Commons:

public int hashCode() {
    new HashCodeBuilder(17, 37).
           append(myString).
           append(myInt);
}

Link qui: http://commons.apache.org /lang/api-2.3/org/apache/commons/lang/builder/HashCodeBuilder.html

E qui:

http://www.koders.com/java/fidCE4E86F23847AE93909a10439 / p>

Altri suggerimenti

Eclipse svolge sempre più o meno la stessa funzione di hashing, ecco un esempio per una classe con campi in e String as

    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + this.interger;
        result = prime * result + ((this.string == null) ? 0 : this.string.hashCode());
        return result;
    }

Selezionano sempre 31 come primo, e poi multipli per build nelle funzioni hash o il valore se è una primitiva. Qualcosa del genere non sarebbe difficile da creare come metodo.

     public int hashCode(Object ... things) {
         final int prime = 31;
         int result = 1;
         for(Object thing : things) {
             result = prime * result + thing.hashCode();
         }
         return result;
     }

Oppure, se non vuoi aggiungere un'altra libreria, fai qualcosa del tipo:

public int hashCode() {
    StringBuilder builder = new StringBuilder();
    builder.append(myString);
    builder.append(myInteger);
    return builder.toString().hashCode();
}

Un metodo hashcode è qualcosa che potenzialmente può essere chiamato molte volte e vale quindi la pena di essere ottimizzato. Se il calcolo è complicato, considerare di memorizzare il valore hash. Inoltre, evitare di fare cose che comportano più calcoli del necessario. (Ad esempio, la soluzione StringBuilder impiega la maggior parte del tempo a creare la stringa temporanea.)

L'altra cosa che voglio sottolineare è che la qualità dell'hash è importante. Vuoi evitare qualsiasi algoritmo hashcode che associ molte chiavi comuni. In tal caso, la ricerca della tabella hash potrebbe non essere più O (1). (Nel peggiore dei casi sarà O (N) ... cioè equivalente a una ricerca lineare!). Ecco un esempio di una cattiva funzione hash:

int hashcode() {
    int hash = 1;
    for (int val : this.values) {
        hash = hash * value;
    }
    return hash;
}

Considera cosa succede se un elemento di this.values ?? è zero ...

Puoi anche usare la classe Objects dal pacchetto java.util.Objects per ottenere rapidamente il codice hash.

@Override
public int hashCode() {
    return Objects.hash(this.string, this.integerValue, this.otherDataTypes);
}

Oltre alla modifica più recente, se la velocità di recupero è più importante dei problemi di archiviazione, è possibile pre-calcolare e memorizzare il codice hash durante la costruzione della classe StringInt . Questo è sicuro poiché hai contrassegnato i campi String e int come final , e anche dato che String è immutabili.

Inoltre, è possibile ottimizzare il metodo equals controllando che l'oggetto che viene confrontato == questo prima di effettuare un confronto completo. Vorrei anche raccomandare di fare il confronto basato su int più economico prima di confrontare i campi di stringa.

Un altro suggerimento finale: è possibile modificare il metodo valueOf (String, int) per costruire un StringInt o restituire un'istanza precedentemente creata se ne esiste già una con lo stesso String e valori int. Questo rende la costruzione più costosa ma i confronti sono molto economici in quanto puoi confrontare StringInt usando " == " sapendo che non saranno mai creati due StringInt con lo stesso valore String e int .

scroll top