初认HashMap
基于哈希表(即散列表)的Map接口的实现,此实现提供所有可选的映射操作,并允许使用null值和null键。
HashMap继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。且是不同步的,意味着它不是线程安全的。
HashMap的数据结构
在java编程语言中,最基本的结构就两种,一个是数组,另一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的。HashMap也不例外,它是一个“链表的数组”的数据结构。从下图中可以看出HashMap的底层就是一个table数组,数组的元素就是Entry。而Entry就是HashMap中的一个存储单元。
Entry的数据结构
table数组中的每个元素都是一个由Entry组成的单向链表,理解这句话对理解HashMap非常重要。
现在来看下单向链表上一个Entry的数据结构以及源码对其的定义
1 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;
HashMap的存取实现
1、存储数据
首先从我编写的这段代码开始,开启HashMap的源码解析之路:
1 public static void main(String[] args) 2 { 3 Map<String,String> hashMap = new HashMap<String,String>(); 4 hashMap.put("语文","89"); 5 hashMap.put("数学","95"); 6 hashMap.put("英语","88"); 7 }
在第3行,创建了一个HashMap
1 public HashMap() { 2 this.loadFactor = DEFAULT_LOAD_FACTOR; 3 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); 4 table = new Entry[DEFAULT_INITIAL_CAPACITY]; 5 init(); 6 }
其中初始容量DEFAULT_INITIAL_CAPACITY为16,loadFactor(负载因子)为0.75。也就是说HashMap在创建的时候构造了一个大小为16的Entry数组。Entry内所有的数据都采用默认值null。
接下来看put方法底层实现是如何的:
1 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 }
1、在2、3两行上,可以看出HashMap允许key值为null的存在,并且存放在数据为0的位置上。
2、
时间: 2024-11-23 22:36:46