HashMap简单原理分析

来源:互联网 发布:mysql 合计函数 编辑:程序博客网 时间:2024/05/19 05:03

感慨现在的在校实习生并不好找实习工作了,就拿安卓而言,想找工作之前还需要一些非常有用的筹码。像自己处于普通本科,只能通过写博客来壮大自己,同时希望加深自己对一些编程的理解。如有什么错误的地方,麻烦你们矫正一下。谢谢~

Hashmap

HashMap面试中经常考的基础题了,HashMap我们都知道是基于哈希表的一种以键值对的方式存储数据。而且查询的时候特别方便,直接通过键的特征就能知道值。那既然这样,你们是否有兴趣去了解其中的奥秘呢 ? 来了,我要开始装逼了。。。。


HashMap是继承自AbstractMap这个父类的。

public class HashMap<K,V> extends AbstractMap<K,V>

先引用一张图哦,本人不会用手残不会作图,只能引用别人的了。
这里写图片描述
这张图发现很多博客都用,我就不标明出处了。如果有侵犯的话请告知。!

我们仔细看一下这张图,作为程序员的我们,是否很熟悉这是什么 ?没错啦,左边是数组,右边就是链表。
所以我们就可以总结出,这是一个散列表。HashMap的底层实现还是用数组实现的,然后数组的每一项,是类似于一条拉链这种形式的。


既然我们知道它的存储原理,接下来我们要知道它是如何实现存储和取值的。我们通常Hashmap的时候,都知道用put和get方式进行的对吧。
那这样我们就进去源码看看,它是怎么实现的,
存储值的时候

int hash = key.hashCode(); // 这个hashCode方法这里不详述,只要理解每个key的hash是一个固定的intint index = hash % Entry[].length;Entry[index] = value;

取值的时候

int hash = key.hashCode();int index = hash % Entry[].length;return Entry[index];

在这两段代码中,发现每次都会int hash这个变量去取key的hashcode,这个意思是说,hashmap是通过hashcode去取值的,那么定位的方式就是,hash % Entry[].length通过这个来赋予index这个变量。举一个简答的例子,就拿上面的第一张图片来解释,在下标为12的位置,12%16=12,28%16=12,108%16=12,140%16=12。那么12,28,108,140都在12的位置。

既然知道这存和取的方式,在Hashmap的内部里面还有一个类,Entry

static class Entry<K,V> implements Map.Entry<K,V> {        final K key;        V value;        Entry<K,V> next;        final int hash;        /**         * Creates new entry.         */        Entry(int h, K k, V v, Entry<K,V> n) {            value = v;            next = n;            key = k;            hash = h;        }        .......    }

这个类是用于存放key和value的,我们可以看到它定义了key value 还有next用于取下一个值,还有hash值。

完整源码

 static class Entry<K,V> implements Map.Entry<K,V> { 2         final K key; 3         V value; 4         Entry<K,V> next;//对下一个节点的引用 5         final int hash;//哈希值 6  7         Entry(int h, K k, V v, Entry<K,V> n) { 8             value = v; 9             next = n;10             key = k;11             hash = h;12         }13 14         public final K getKey() {15             return key;16         }17 18         public final V getValue() {19             return value;20         }21 22         public final V setValue(V newValue) {23         V oldValue = value;24             value = newValue;25             return oldValue;//返回的是之前的Value26         }27 28         public final boolean equals(Object o) {29             if (!(o instanceof Map.Entry))//判断类型是否一致30                 return false;31             Map.Entry e = (Map.Entry)o;32             Object k1 = getKey();33             Object k2 = e.getKey();34             //如果Key相等和Value相等则两个Entry相等35             if (k1 == k2 || (k1 != null && k1.equals(k2))) {36                 Object v1 = getValue();37                 Object v2 = e.getValue();38                 if (v1 == v2 || (v1 != null && v1.equals(v2)))39                     return true;40             }41             return false;42         }43         // hashCode是Key的hashCode和Value的hashCode的异或的结果44         public final int hashCode() {45             return (key==null   ? 0 : key.hashCode()) ^46                    (value==null ? 0 : value.hashCode());47         }48         // 输出49         public final String toString() {50             return getKey() + "=" + getValue();51         }52 53          56         void recordAccess(HashMap<K,V> m) {57         }58 59       62         void recordRemoval(HashMap<K,V> m) {63         }64     }

put操作

public V put(K key, V value) { 2         if (key == null) 3             return putForNullKey(value); 4         int hash = hash(key.hashCode()); 5         int i = indexFor(hash, table.length); 6         for (Entry<K,V> e = table[i]; e != null; e = e.next) { 7             Object k; 8             if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 9                 V oldValue = e.value;10                 e.value = value;11                 e.recordAccess(this);12                 return oldValue;13             }14         }15 16         modCount++;17         addEntry(hash, key, value, i);18         return null;19     }

get操作

 public V get(Object key) { 2         if (key == null) 3             return getForNullKey(); 4         int hash = hash(key.hashCode()); 5         for (Entry<K,V> e = table[indexFor(hash, table.length)]; 6              e != null; 7              e = e.next) { 8             Object k; 9             if (e.hash == hash && ((k = e.key) == key || key.equals(k)))10                 return e.value;11         }12         return null;13     }
原创粉丝点击