Java 8 HashMap

Time:2019-11-5

HashMap uses array, linked list and red black tree to store key value pairs. When the linked list is long enough, it will be converted to red black tree. HashMap is non thread safe.

Constants in HashMap

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
static final int MAXIMUM_CAPACITY = 1 << 30;
static final float DEFAULT_LOAD_FACTOR = 0.75f;
static final int TREEIFY_THRESHOLD = 8;
static final int UNTREEIFY_THRESHOLD = 6;
static final int MIN_TREEIFY_CAPACITY = 64;
  • DEFAULT_INITIAL_CAPACITYThe initial capacity is 16.
  • MAXIMUM_CAPACITYMaximum capacity 230
  • DEFAULT_LOAD_FACTORDefault fill factor. In the initial case, when the number of key value pairs is greater than 16 * loading factor, the capacity will be doubled.
  • TREEIFY_THRESHOLDWhen the length of the list reaches this value, it is possible to convert it to a tree.
  • UNTREEIFY_THRESHOLDWhen the length of the list is less than this value, it will degenerate from tree to list.
  • MIN_TREEIFY_CAPACITYBefore converting to a tree, a judgment will be made. Only when the number of key value pairs is greater than the value, the tree will be converted to a red black tree. If it is less than the value, only the capacity expansion will be triggered.

The capacity in HashMap uses the shift operation. Shifting a number a left by N bits is equivalent to: a = a * 2n, so 1 < 4 = > 1 * 24= 16. Therefore, the capacity of HashMap is always n power of 2.

Using the parametric construction method, you can specify the initial capacity and loading factor, and the specified capacity will be adjusted upward to the N-power of 2 (for example, if the given capacity is 13, it will be adjusted to 16).

The value of key value pair in HashMap can be null, and a key value pair with null key can exist.

Some methods of HashMap

Treeifybin method

/**
 * Replaces all linked nodes in bin at index for given hash unless
 * table is too small, in which case resizes instead.
 */
final void treeifyBin(Node[] tab, int hash) {
    int n, index; Node e;
    //Determine whether the threshold value of conversion to tree is reached
    if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
        Resize(); // if it is not reached, just expand the capacity.
    else if ((e = tab[index = (n - 1) & hash]) != null) {
        TreeNode hd = null, tl = null;
        do {
            TreeNode p = replacementTreeNode(e, null);
            if (tl == null)
                hd = p;
            else {
                p.prev = tl;
                tl.next = p;
            }
            tl = p;
        } while ((e = e.next) != null);
        if ((tab[index] = hd) != null)
            hd.treeify(tab);
    }
}

In callputMethod, if the number reachesTREEIFY_THRESHOLD, will calltreeifyBinMethod, this method will judge whether the length of the table reachesMIN_TREEIFY_CAPACITYOtherwise, the table will be converted to a tree.

The (n – 1) – hash here is the complement operation, which is equivalent to hash% N, because the length of HashMap is always n power of 2.

Replaceall method

@Override
public void replaceAll(BiFunction super K, ? super V, ? extends V> function) {
    Node[] tab;
    if (function == null)
        throw new NullPointerException();
    if (size > 0 && (tab = table) != null) {
        int mc = modCount;
        for (int i = 0; i < tab.length; ++i) {
            for (Node e = tab[i]; e != null; e = e.next) {
                e.value = function.apply(e.key, e.value);
            }
        }
        if (modCount != mc)
            throw new ConcurrentModificationException();
    }
}

This method accepts a lambda expression and replaces the values that meet the given conditions, such as:

HashMap map = ...;
//Replace the value of all key value pairs whose key is even with "foo"
map.replaceAll((k, v) -> k % 2 == 0 ? "foo" : v);

Foreach method

@Override
public void forEach(BiConsumer super K, ? super V> action) {
    Node[] tab;
    if (action == null)
        throw new NullPointerException();
    if (size > 0 && (tab = table) != null) {
        int mc = modCount;
        for (int i = 0; i < tab.length; ++i) {
            for (Node e = tab[i]; e != null; e = e.next)
                action.accept(e.key, e.value);
        }
        if (modCount != mc)
            throw new ConcurrentModificationException();
    }
}

The method also accepts a lambda expression for consuming key value pairs:

//Print all key value pairs
map.forEach(
    (k, v) -> System.out.println(k + ": " + v)
);

//Print all even key value pairs
map.forEach(
    (k, v) -> {
        if (k % 2 == 0)
            System.out.println(k + ": " + v)
    }
);

Recommended Today

The use of progressbarcontrol, a progress bar control of devexpress – Taking ZedGraph as an example to add curve progress

scene WinForm control – devexpress18 download installation registration and use in vs: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100061243 When using ZedGraph to add curves, the number of curves is slower if there are many cases. So in the process of adding curve, the progress needs to be displayed, and the effect is as follows     Note: Blog home page:https://blog.csdn.net/badao_liumang_qizhi […]