2009-07-30 6 views
11

Je me souviens qu'eclipse et idea ont ce modèle pour créer automatiquement le hashCode d'un objet en fonction de ses attributs.Créer un hachage à partir de string et int

L'une des stratégies si un nombre et une chaîne est utilisée est quelque chose comme ceci.

return stringValue.hashCode() + intValue * 32; 

Ooor quelque chose comme ça.

Je n'ai ni éclipse ni idée à portée de main et j'aimerais créer une telle fonction.

EDIT

Sur la base des réponses que je crée ce 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; 
     } 
    } 

Cette classe doit être utilisé comme clé pour une grande carte mémoire (> 10k éléments) Je ne suis pas vouloir les parcourir chaque fois pour trouver si le String et l'int sont les mêmes.

Merci.

ps .. mmh probablement les noms StringIntKey.

+0

Oscar, je pense que c'est une bonne classe. La méthode hashCode est claire, fiable et performante. Qu'en est-il de la prévention d'une chaîne nulle? Dans votre constructeur, lancez un NPE s'il est nul. Ensuite, vous pouvez supprimer ces gardes nuls dans equals et hashCode. Enfin, gardez une copie de "Java efficace" à portée de main pour les questions comme celles-ci. Les méthodes hashCode créées par Eclipse et IDEA sont basées sur ce livre. –

+0

Dans votre méthode égale, vous devez comparer l'utilisation de la chaîne à la place de ==. –

Répondre

8

Utiliser Apache Commons HashcodeBuilder:

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

Lien ici: http://commons.apache.org/lang/api-2.3/org/apache/commons/lang/builder/HashCodeBuilder.html

Et ici:

http://www.koders.com/java/fidCE4E86F23847AE93909CE105394B668DDB0F491A.aspx

+0

Le code source de HashCodeBuilder est-il en ligne? ... Je vais le regarder. – OscarRyz

+0

il est dit: string.hashCode * 37 + intValue !! assez pour moi !! Merci – OscarRyz

3

Ou, si vous ne voulez pas ajouter une autre bibliothèque , faites quelque chose comme ce qui suit:

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

Doh! .. parfois je manque ce genre de solutions !! Oui, je ne veux pas ajouter une autre bibliothèque. Merci pour le conseil – OscarRyz

+2

@aperkins: il est plus simple d'écrire simplement "return (myString + myInteger) .hashCode()". Le compilateur Java compilera ceci à la séquence équivalente d'appels StringBuilder.append. –

+2

@perkins: autre chose, si vous êtes vraiment préoccupé par la vitesse, alors cette approche est significativement plus lente que le calcul et la combinaison des hashcodes des composants. –

3

Eclipse fait toujours à peu près la même fonction de hachage, voici un exemple pour une classe avec une et chaîne comme champs

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

Ils choisissent toujours 31 comme le premier, puis multiple par l'accumulation dans les fonctions de hachage ou la valeur si c'est une primitive. Quelque chose comme ça ne serait pas difficile à créer en tant que méthode.

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

Suite à votre édition la plus récente, si la vitesse de récupération est plus important que les problèmes de stockage vous pourriez précalculer et stocker le code de hachage lors de la construction de votre classe StringInt. Ceci est sûr car vous avez marqué les champs String et int comme final, et aussi étant donné que String est immuable.

En outre, vous pouvez optimiser votre méthode equals en vérifiant que l'objet est comparé == this avant de faire une comparaison complète. Je recommande également de faire d'abord la comparaison basée sur l'int moins coûteuse avant de comparer les champs de chaîne. Une autre suggestion finale: Vous pouvez modifier votre méthode valueOf(String, int) pour construire un StringInt ou renvoyer une instance précédemment créée s'il en existe déjà une avec les mêmes valeurs String et int.Cela rend la construction plus chère mais les comparaisons sont très bon marché car vous pouvez comparer StringInt en utilisant "==" en sachant qu'il n'y aura jamais deux StringInt qui seront créés avec les mêmes valeurs String et int.

1

Une méthode de code de hachage est quelque chose qui peut être appelé de nombreuses fois, et vaut donc la peine d'être optimisé. Si le calcul est compliqué, pensez à mémoriser la valeur de hachage. Aussi, évitez de faire des choses qui impliquent plus de calculs que nécessaire. (Par exemple, la solution StringBuilder passe le plus clair de son temps à créer la chaîne temporaire.)

L'autre chose que je veux souligner est que la qualité du hachage est importante. Vous voulez éviter tout algorithme de hachage qui mappe beaucoup de clés communes. Si cela se produit, la recherche dans la table de hachage peut ne plus être O (1). (Dans le pire des cas, ce sera O (N) ... c'est-à-dire équivalent à une recherche linéaire!). Voici un exemple d'une mauvaise fonction de hachage:

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

Tenir compte ce qui se passe si un élément de this.values est nul ...

0

Vous pouvez également utiliser Objects classe de java.util.Objects package pour obtenir rapidement le code de hachage.

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