Ce qui est un bon premier pour hashcode de calcul?

Eclipse 3.5 a une caractéristique très intéressante pour générer Java hashCode() de fonctions. Il pourrait générer, par exemple (légèrement raccourcie:)

class HashTest {
    int i;
    int j;        
    public int hashCode() {
        final int prime = 31;
        int result = prime + i;
        result = prime * result + j;
        return result;
    }
}

(Si vous avez plus d'attributs dans la classe, result = prime * result + attribute.hashCode(); est répété pour chaque attribut supplémentaire. Pour ints .hashCode() peut être omis.)

Cela semble bien, mais pour le choix 31 pour le premier. C'est probablement à partir de la hashCode de la mise en œuvre de Java String, qui a été utilisé pour des raisons de performances qui ont disparu depuis longtemps après l'introduction de matériel de multiplication. Ici, vous avez beaucoup de hashcode collisions pour les petites valeurs de i et de j: par exemple (0,0) et (-1,31) ont la même valeur. Je pense que c'est une Mauvaise Chose(TM), depuis les petites valeurs se produisent souvent. Pour La Chaîne.hashCode vous trouverez également de nombreuses chaînes courtes avec le même hashcode, par exemple "Ca" et "DB". Si vous prenez une grande le premier, ce problème disparaît si vous choisissez le premier à droite.

Donc ma question: qu'est ce qu'un bon premier choisir? Quels critères avez-vous d'appliquer pour le trouver?

Il ne s'agit que d'une question d'ordre général - donc, je ne veux pas donner une gamme de i et j. Mais je suppose que, dans la plupart des applications relativement petites valeurs se produisent plus souvent que les grandes valeurs. (Si vous avez de grandes valeurs, le choix de la prime est probablement sans importance.) Il ne pourrait pas faire beaucoup de différence, mais un meilleur choix est un moyen facile et évident pour améliorer cette - alors, pourquoi ne pas le faire? Commons lang HashCodeBuilder suggère aussi curieusement petites valeurs.

(Clarification: c'est pas un double de Pourquoi Java est hashCode() en Chaîne de caractères utilisez 31 comme un multiplicateur? depuis que ma question n'est pas concerné par l'histoire de la 31 dans le JDK, mais sur ce que serait une meilleure valeur dans le nouveau code en utilisant le même modèle de base. Aucune des réponses, essayer de répondre à cela.)

  • 31 est toujours bon qu'il ne s'agit pas nécessairement de chargement d'une constante. Sur un processeur ARM (au moins celle qui est utilisée par environ 99.9997% des téléphones mobiles) *31 ne peut être en une seule instruction. Dans la réalité, n'importe quel nombre impair si le premier ou qui n'est pas bonne suffisant.
  • Je pensais à des programmes de bureau, où il n'a pas d'importance si vous choisissez 31 ou 1327144003. Curieusement, sur ma machine multipliant avec 31 est en fait un peu plus lent - sans doute une optimisation est mal passé. 😎
  • Les nombres premiers de la forme p = (2^n-1) se prêtent à l'optimisation de x * p = (p << n) - p qui le compilateur le fait habituellement. De Joshua Bloch, Efficace Java, Chapitre 3, Article 9. DONC, la question stackoverflow.com/questions/299304/...
  • et de se multiplier avec les integer <128 ont un élan supplémentaire à la jvm.. 2^n-1, le premier, petite .. ce qui donne à 31.
  • Comme je l'ai dit, pour le courant des machines de bureau, cela ne semble pas être une optimisation plus - le temps est le même. Pire encore: sur ma machine multipliant avec 31 a été un peu plus lente, peut-être que la JVM essayé pour "optimiser" par le calcul de x << 5 - x, et c'est effectivement plus lent que d'utiliser le matériel multiplicateur.
  • Sur i86, il y a une différence, car il y a un mode pour un seul octet immédiate opérande. Vous obtenez une courte instruction et d'un indice de référence que j'ai écrit il y a des années, il a été un peu plus rapide.
  • Veuillez noter que ceci est très différent de [Pourquoi Java est hashCode() en Chaîne de caractères utilisez 31 comme un multiplicateur?][1] puisque ce n'est pas à propos de l'histoire de l'31, mais sur ce que serait un meilleur choix au lieu d'utiliser 31, sans l'aide d'autres bibliothèques ou entièrement différentes méthodes de calcul de tables de hachage. Aucune des réponses adresses. [1]: stackoverflow.com/questions/299304/...