web-dev-qa-db-fra.com

deux objets inégaux avec le même hashcode

Le concept Hashcode () et equals () est

1) Si deux objets sont égaux selon equal (), alors appeler la méthode hashcode sur chacun de ces deux objets devrait produire le même hashcode.

et l'autre est

2) Il n'est pas nécessaire que si deux objets sont inégaux selon l'égal (), alors appeler la méthode hashcode sur chacun des deux objets doit produire des valeurs distinctes.

J'ai essayé et compris le premier et c'est le code pour le premier point.

public class Test {
    public static void main(String[] args) {

        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        map.put(1, 11);
        map.put(4, 11);
        System.out.println(map.hashCode());
        Map<Integer, Integer> map1 = new HashMap<Integer, Integer>();
        map1.put(1, 11);
        map1.put(4, 11);
        System.out.println(map1.hashCode());
        if (map.equals(map1)) {
            System.out.println("equal ");
        }
    }
}

le programme ci-dessus donne le même code de hachage pour deux objets différents.

Quelqu'un peut-il m'expliquer avec un exemple, comment deux objets différents qui sont inégaux selon equals () peuvent-ils avoir le même hashcode.

15
Saha

2) Il est non requis que si deux objets sont inégaux selon l'égal (), alors appeler la méthode hashcode sur chacun des deux objets doit produire des valeurs distinctes.

Selon la fonction de hachage, 2 objets différents peuvent avoir le même code de hachage. Cependant, 2 objets identiques doivent produire le même résultat lors du hachage (sauf si quelqu'un a implémenté une fonction de hachage avec des nombres aléatoires, auquel cas elle est inutile)

Par exemple, si je hache des entiers et que ma fonction de hachage est simplement (n % 10) puis le nombre 17 et le nombre 27 produira le même résultat. Cela ne signifie pas que ces chiffres sont les mêmes.

26
Jonathan

Exemple avec des chaînes (toutes les chaînes ci-dessous ont un code de hachage de 0):

public static void main(String[] args) {
    List<String> list = Arrays.asList("pollinating sandboxes",
                                      "amusement & hemophilias",
                                      "schoolworks = perversive",
                                      "electrolysissweeteners.net",
                                      "constitutionalunstableness.net",
                                      "grinnerslaphappier.org",
                                      "BLEACHINGFEMININELY.NET",
                                      "WWW.BUMRACEGOERS.ORG",
                                      "WWW.RACCOONPRUDENTIALS.NET",
                                      "Microcomputers: the unredeemed Lollipop...",
                                      "Incentively, my dear, I don't tessellate a derangement.",
                                      "A person who never yodelled an apology, never preened vocalizing transsexuals.");
    for (String s : list) {
        System.out.println(s.hashCode());
    }
}

(volé à ce post ).

8
assylias

hashCode () a des valeurs possibles de 32 bits. Vos objets peuvent avoir beaucoup plus que cela, vous allez donc avoir des objets avec le même hashCode, c'est-à-dire que vous ne pouvez pas vous assurer qu'ils seront uniques.

Cela est aggravé dans une collection de hachage d'une taille limitée. La capacité maximale de HashMap est de 1 << 30 ou environ un milliard. Cela signifie que seulement 30 bits sont vraiment utilisés et si votre collection n'utilise pas 16+ Go et ne représente que mille compartiments (ou 1 << 10 techniquement), alors vous n'avez vraiment que 1000 compartiments possibles.

Remarque: sur la machine virtuelle Java HotSpot, le Object.hashCode () par défaut n'est jamais négatif, c'est-à-dire seulement 31 bits, mais je ne sais pas pourquoi.

Si vous souhaitez générer de nombreux objets avec le même hashCode, regardez Long.

// from Long
public int hashCode() {
    return (int)(value ^ (value >>> 32));
}

for(long i = Integer.MIN_VALUE; i < Integer.MAX_VALUE;i++) {
    Long l = (i << 32) + i;
    System.out.print(l.hashCode()+" ");
    if (i % 100 == 0)
        System.out.println();
}

Cela générera 4 milliards de Longs avec un hashCode de 0.

6
Peter Lawrey

Je ne suis pas assez simple à comprendre si vous savez comment un HashMap est implémenté et son but. Un Hashmap prend un grand ensemble de valeurs et les divise en ensembles beaucoup plus petits (compartiments) pour une récupération beaucoup plus rapide des éléments. Fondamentalement, il vous suffit de rechercher le seul compartiment au lieu de la liste complète pour votre élément. Les compartiments sont dans un tableau où l'index est le code de hachage. Chaque compartiment contient une liste d'éléments liés avec le même code de hachage, mais ils ne sont pas égaux (). Je pense qu'en Java 8, ils sont passés à l'utilisation d'un treemap lorsque les tailles de compartiment deviennent grandes.

2
Steven Rock

Le but de hashCode est d'activer l'axiome et le corollaire suivants:

  • S'il se trouve que vous connaissez les codes de hachage de deux objets, et que ces codes de hachage ne correspondent pas, il n'est pas nécessaire d'examiner plus à fond les objets pour savoir que les objets ne correspondront pas. Même si deux objets non correspondants choisis arbitrairement avaient 10% de chances d'avoir des codes de hachage correspondants, le test des codes de hachage permettrait d'éliminer 90% des comparaisons dont on aurait autrement besoin. Pas une victoire aussi importante que l'élimination de 99,99%, mais cela en vaut vraiment la peine.

  • La connaissance qu'aucun des objets d'un groupe n'a un code de hachage particulier implique qu'aucun des objets de ce groupe ne correspondra à un objet avec ce code de hachage. Si l'on partitionnait une collection d'objets en ceux dont le code de hachage était un nombre pair et ceux dont le hachage était impair, et si l'on voulait savoir si l'on avait un élément donné dont le code de hachage était pair, il n'y aurait pas besoin d'examiner quoi que ce soit. dans la collection d'articles de hachage impair. De même, il ne serait pas nécessaire de rechercher un élément de hachage impair dans la collection de hachage pair. Même un hachage à deux valeurs pourrait ainsi accélérer de près de moitié les recherches. Si l'on divise une collection en plus petites partitions, on peut accélérer encore plus les choses.

Notez que hashCode() offrira le plus d'avantages si chaque élément différent renvoie un hachage différent, mais il peut offrir des avantages substantiels même lorsque de nombreux éléments ont la même valeur de hachage. La différence entre une économie de 90% et une économie de 99,99% est souvent beaucoup plus grande que les chiffres ne le suggèrent, et donc une si l'on peut raisonnablement facilement améliorer les choses à 99%, 99,9% ou mieux, il faut le faire, mais la différence entre avoir zéro fausses correspondances et avoir quelques fausses correspondances dans une collection est assez léger.

1
supercat

C'est assez simple en fait,

Nous devons d'abord savoir ce qu'est un code de hachage.

En Java, un code de hachage est un simple entier signé de 32 bits qui est en quelque sorte dérivé des données en question. Les types entiers sont généralement juste (Int Data) Mod (un certain nombre premier raisonnable).

Faisons un hachage simple sur les entiers.
Définir:

public int hash(int num){ return num % 19 ; } 

Dans ce cas, 19 et 38 renverront la valeur de hachage de 0.

Pour les types de chaîne, le hachage est dérivé des caractères individuels et de la position de chacun dans la chaîne, divisé par un nombre raisonnablement élevé. (Ou, dans le cas de Java, ignorer le débordement dans une somme de 32 bits).

Étant donné qu'il existe arbitrairement de nombreuses chaînes possibles et qu'il existe un nombre limité de codes de hachage (2 ^ 32) pour une chaîne, le principe du pigeon-hole indique qu'il existe au moins deux chaînes différentes qui aboutissent au même code de hachage.

0
Chris Cudmore

En fait, ce lien explique ce qui se passe si le code de hachage est plus clair.

http://www.javamadesoeasy.com/2015/02/hashmap-custom-implementation.html

0
madhu_karnati

Je crois que cela vous aidera à comprendre ...

Le code de hachage d'un objet Java est simplement un nombre, il est signé 32 bits int, ce qui permet à un objet d'être géré par une structure de données basée sur le hachage. Nous savons que le code de hachage est un numéro d'identification unique attribué à un objet par la machine virtuelle Java. Mais en réalité, le code de hachage n'est pas un numéro unique pour un objet. Si deux objets sont égaux, ces deux objets doivent renvoyer le même code de hachage. Nous devons donc implémenter la méthode hashcode () de une classe de telle sorte que si deux objets sont égaux, c'est-à-dire comparés par la méthode equal () de cette classe, ces deux objets doivent renvoyer le même code de hachage. Si vous remplacez hashCode, vous devez également remplacer la méthode equals.

réf: https://www.Java2novice.com/Java_interview_questions/hashcode/

0
Vladimir Yel