4

I opened HashMap source code (Java 8+) and checked the put() method. In Java 7 (and less) the source code was kinda simple, but I can't understand the Java 8+ version.

If element in bucket doesn't exist, we just put it into HashMap:

if ((p = tab[i = (n - 1) & hash]) == null)
    tab[i] = newNode(hash, key, value, null);

But if element already exist we meet collision.

At the beginning in "else" block we compare element (?) with (what? first element in this bucket?) by their hash(?):

else {
    if (p.hash == hash &&
        ((k = p.key) == key || (key != null && key.equals(k))))
        e = p;

But, wait, we did it again later there:

    ...
    else {
        for (int binCount = 0; ; ++binCount) {
            if ((e = p.next) == null) {
                p.next = newNode(hash, key, value, null);
                if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                    treeifyBin(tab, hash);
                break;
            }
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                break;
            p = e;
        }
    }
    ...
}

We traversed the list until the end and compared the new element with all elements (for loop) in bucket. So, I don't understand the purpose of the first comparison. Does it (first case) mean that we compare last added element (already in hashmap) with new "ready to add" element if they are not in same bucket?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
dogyears
  • 57
  • 4
  • 2
    First if; checks if the table row has no items; if so, add this node as the first. Else, next if; checks if the first element is the one of interest (set it to e if so, to be set in code below what you've pasted). Else, if the next element is null, then we need to add the new element; add it. Else, check if the element is the one of interest. If so, we will break (and update e as below). Else, set p to e and continue searching through. Could have been wrote differently to make the if in the first else handled by the later blurb, but would involve changing the logic a little. – Ironcache Jan 20 '20 at 18:43
  • First element = first element (head) of linked list inside the bucket? Did I understand this right? If yes, still don't understand why we compare elements with the head of linked list separately if we can compare them in one for loop. – dogyears Jan 21 '20 at 09:42
  • After 1 hour I finally understand why we compare with first element separately, huh! – dogyears Jan 21 '20 at 11:59

1 Answers1

-2

Line 629 (if ((p = tab[i = (n - 1) & hash]) == null)) could be written on three separate lines:

i = (n - 1) & hash;
p = tab[i];
if (p == null)
    { ... }

Then the assignments are more visible, and it is more obvious that they are executed prior to the else block.

dsh
  • 12,037
  • 3
  • 33
  • 51