HashMap简单原理分析

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

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;//返回的是之前的Value
26         }
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     }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值