HashMap的基本原理:

HashMap是基于哈希算法,然后调用get()和put()方法进行数据的读取和存入。

首先看一下HashMap的存储形式:

android HashMap 存值取值 hashmap的存取原理_链表

数据的存储put()方法

 1. 当我们将键值对传递给HashMap的put()方法时,它就会调用对象的hashCode()方法计算对应的hashCode值,根据hashCode值找到对应的bucket位置来进行存储对象。

 2.此时,找到bucket位置后,不会立即去存储键值对,而是通过循环变量查询对应bucket索引后面的数据,调用equals()方法查看是否有与存入的数据的key相同的数据存在(因为HashMap中没有重复的数据存在),当找到有key值相同时,就将新的value值替换旧的value值,并返回旧的value值,如果没有相同的key存在,就直接在索引(也就是链表)前面插入该key-value键值对。如下代码:

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的keyCode重新计算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.}


数据读取get()方法:                                                                                                                                                                  

我们都知道HashMap存储的值key-value键值对,所以,当对数据进行查询读取时,是根据key值进行查询。


1. 将key值给get(key)方法后,就会首先调用对象的hashCode()方法,获得此key值对应的hashCode值,根据hashCode值找

到对应的bucket位置。

2. 找到bucket位置后,就是用equals()方法开始遍历后面的一组数据。如果找到key值相同的数据,就返回,如果没有找到就

返回null.

源代码如下:


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方法在对应位置的链表中找到需要的元素



 归纳起来简单地说,HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,当需要存储一个 Entry 对象时,会根据hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。