Java HashMap源码小结

本文详细介绍了Java中的HashMap数据结构,包括其实现原理、关键方法解析及与其他集合类的区别。深入探讨了HashMap的底层实现机制,如容量、装载因子、冲突解决策略等。

本文基于jdk1.8.

HashMap即哈希表,是一种能以常数平均时间完成插入,删除和查找操作的数据结构;

哈希表有两种实现方式:开放地址方式和冲突链表方式;开放地址方式不需要使用链表,但是要频繁的再散列操作,常用的再散列方法有线性探测法,平方探测法,双散列法。冲突链表方式将所有哈希值相同的键用链表串起来,理想情况下的哈希表每个哈希值对应一个键,此时查找操作为常数时间;

有两个参数与哈希表的性能有关:容量Capacity和装载因子load_factor,Threshold=Capacity * load_factor;

哈希表默认的容量是2^4;最大容量是2^30;装载因子默认为0.75;

当装入哈希表的元素大于threshold时,哈希表自动扩容,容量变为原来2倍,扩容后元素顺序会被打散,在不同时间遍历哈希表得到的结果可能不同;

在jdk1.8中,链表过长的话(长度>8),HashMap会将冲突链表转化为红黑树;

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

其底层实现是由数组和链表构造而成,如图:


1. get(Object key)

public V get(Object key) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }
通过传入key得到value;

2. getNode(int hash, Object key)

final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {
            if (first.hash == hash && // always check first node
                ((k = first.key) == key || (key != null && key.equals(k))))
                return first;
            if ((e = first.next) != null) {
                if (first instanceof TreeNode)
                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);
                do {
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);
            }
        }
        return null;
    }
tab[n-1]&hash是确定key在哈希表中的位置;

然后在链表中寻找(k==key || key.equals(k)),找k是否==key或equals key;返回Node;

若需要将自定义的对象放入HashMap中,需要override equals方法和hashCode方法;
3. containsKey(Object key)

public boolean containsKey(Object key) {
        return getNode(hash(key), key) != null;
    }
判断哈希表中是否存在这个key;

4. put

public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
将一个键值对插入哈希表;

5.remove

public V remove(Object key) {
        Node<K,V> e;
        return (e = removeNode(hash(key), key, null, false, true)) == null ?
            null : e.value;
    }
将key对应的Node从哈希表中删除;


和其他集合类的比较:HashSet采用了适配器模式(HashSet里有一个HashMap);HashMap没有实现同步,HashTable实现了同步,其余类似;HashMap元素无序,TreeMap元素有序;

参考文章:https://zhuanlan.zhihu.com/p/24828513


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值