浅析JAVA集合框架之HashMap

注:

本文基于jdk1.8

XiuQiang:~ XiuQiang$ java -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

Capacity和Size的区别

Capacity:容量,哈希桶数组的长度,即table.length。
Size:哈希桶数组内节点的总数。

数据结构

  HashMap底层的数据结构是数组+链表+红黑树(jdk1.7是数组+链表)。
  在下文中,我们将哈希桶数组里可以存储元素的位置称为桶(bucket)。同时,将桶中链表或者红黑树的节点称之为bin。(bin是依据是源码中的注释,不是我一拍脑袋随便想出来的哈)
在这里插入图片描述
图来自郑加威的博客:传送门
  当桶中的结构为链表时,HashMap采用Node数组来存储key-value对,每一个键值对组成了一个Node实体,即bin。Node类具有Next指针,可以连接下一个Node实体,依此来解决hash冲突的问题。

什么是hash冲突

HashMap是按照Key的hash值来计算bin在HashMap中存储的位置的,即桶的位置。如果hash值相同,而key内容不相等,它们就会被放入同一个桶内。此时就要用链表来解决这种hash冲突。当桶内链表长度大于8时,链表会转化为红黑树,这种转换是有条件的,若桶的数量太少,则会直接进行扩容。欲知后事如何,请听下回分解,哈哈哈哈。

什么是链表

  链表是由一系列非连续的节点组成的存储结构,简单分下类的话,链表又分为单向链表和双向链表,而单向/双向链表又可以分为循环链表和非循环链表。因为HashMap中的链表就是单向链表,下面简单就单向链表进行图解说明。其他几种链表感兴趣的同学可以自行查阅资料。

单向链表

  单向链表就是通过每个结点的指针指向下一个结点从而链接起来的结构,最后一个节点的next指向null。
单向链表

Node实体

 /**
     * Basic hash bin node, used for most entries.  (See below for
     * TreeNode subclass, and in LinkedHashMap for its Entry subclass.)
     */
    static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        public final K getKey()        { return key; }
        public final V getValue()      { return value; }
        public final String toString() { return key + "=" + value; }

        public final int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }

        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

        public final boolean equals(Object o) {
            if (o == this)
                return true;
            if (o instanceof Map.Entry) {
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                if (Objects.equals(key, e.getKey()) &&
                    Objects.equals(value, e.getValue()))
                    return true;
            }
            return false;
        }
    }

什么是红黑树

 红黑树是一种自平衡的二叉查找树,在原有的二叉查找树基础上增加了如下几个要求:

  1. Every node is either red or black.(节点是红色或黑色)
  2. The root is black.(根节点是黑色)
  3. Every leaf (NIL) is black.(每个叶子节点都是黑色的空节点(NIL节点))
  4. If a node is red, then both its children are black.(每个红色节点的两个子节点都是黑色)
  5. For each node, all simple paths from the node to descendant leaves contain the same number of black nodes.(从任意节点到其每个叶子的所有路径都包含相同树木的黑色节点)
    在这里插入图片描述
    感兴趣的同学可以看下下面这篇文章,此处就不再赘述了。
    漫画算法:什么是红黑树?

TreeNode实体

    /**
     * Entry for Tree bins. Extends LinkedHashMap.Entry (which in turn
     * extends Node) so can be used as extension of either regular or
     * linked node.
     */
    static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
        TreeNode<K,V> parent;  // red-black tree links
        TreeNode<K,V> left;
        TreeNode<K,V> right;
        TreeNode<K,V> prev;    // needed to unlink next upon deletion
        boolean red;
        TreeNode(int hash, K key, V val, Node<K,V> next) {
            super(hash, key, val, next);
        }
        //此处省略一万字...

源码阅读

继承与实现接口

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable

在这里插入图片描述

类的属性

// 默认初始容量
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 
//最大容量
static final int MAXIMUM_CAPACITY = 1 
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值