HashMap

   HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是不能保证该顺序恒久不变。

   HashMap的数据结构:

   在java中,最基本的结构有两种:一是数组,而是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。

  

HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap时,就会初始化一个数组。

1 transient Entry[] table;
2 static class Entry<k,V> implements Map.Entry<K,V>{
3     final K key;
4     V value;
5     Entry<K,V> next;
6     final int hash;
7     ......
8 }

可以看出,Entry就是数组中的元素,每个Map.Entry其实就是一个key-value对,它持有一个指向下一个元素的引用,这就构成了链表。

  HashMap的存取实现:

  1)存储:

 1 public V put(K key,V value){
 2     //HashMap允许存放null值和null键
 3     //当key为null时,调用putForNullKey方法,将value放置在数组的一个位置。
 4     if(key==null)
 5         return putForNullKey(value);
 6     //根据key的hashCode重新计算hash值
 7     int hash=hash(key.hashCode());
 8     //搜索指定hash值在对应table中的索引
 9     int i=indexFor(hash,table.length);
10     //如果i索引处的Entry不为null,通过循环不断遍历e元素的下一个元素。
11     for(Entry<K,V> e=table[i];e!=null;e=e.next){
12         Object k;
13         if(e.hash==hash&&((k=e.key)==key||key.equals(k))){
14             V oldValue = e.value;
15             e.value = value;
16             e.recordAccess(this);
17             return oldValue;
18         }
19     }
20 // 如果i索引处的Entry为null,表明此处还没有Entry。
21     modCount++;
22     // 将key、value添加到i索引处。
23     addEntry(hash, key, value, i);
24     return null;
25 }

从上面的源码中可以看出:当我们往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放了其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。

  2)读取:

public V get(Object key) {
    if (key == null)
        return getForNullKey();
    int hash = hash(key.hashCode());
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
        e != null;
        e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
            return e.value;
    }
    return null;
}

有了上面存储时的hash算法作为基础,理解起来这段代码就很容易了。从上面的源代码中可以看出:从HashMap中get元素时,首先计算key的hashCode,找到数组中对应位置的某一元素,然后通过key的equals方法在对应位置的链表中找到需要的元素。

  以上内容摘抄自http://beyond99.blog.51cto.com/1469451/429789

    

HashMap使用了特殊的值,称作散列码,来取代对键的缓慢搜索。散列码是“相对唯一”的、用以代表对象的int值,它是通过将该对象的某些信息进行转换而生成的。hashCode()是根类Object中的方法,因此所有的Java对象都能产生散列码。HashMap就是使用对象的hashCode()进行快速查询的,此方法能显著提高性能。

原文地址:https://www.cnblogs.com/dazuihou/p/3576352.html