[Java]JDK源码学习(3)HashMap
来源:互联网 发布:python与php哪个好学 编辑:程序博客网 时间:2024/05/18 00:13
首先我们知道HashMap是线程不安全的,所以要避免多个线程共享操作
HashMap的数据结构
HashMap主要是通过数组(transient Entry[] table)来存储数据的,通过key得到hash值后找到数组中相对应的位置,如果有冲突,则是用链表来解决的,请看Entry的属性
final K key;
V value;
Entry<K,V> next;
final int hash;
这里的next就是为了哈希冲突而存在的。比如通过哈希运算,一个新元素应该在数组的第10个位置,但是第10个位置已经有Entry,那么好吧,将新加的元素也放到第10个位置,将第10个位置的原有Entry赋值给当前新加的 Entry的next属性。数组存储的是链表,链表是为了解决哈希冲突的,这一点要注意。
先看几个HashMap里的字段
static final int MAXIMUM_CAPACITY = 1 << 30;
DEFAULT_LOAD_FACTOR = 0.75;
static final int DEFAULT_INITIAL_CAPACITY = 16;
:这是用来存储数据的,这个数组同样不会序列化,具体不再累述
transient int size:表示当前存储数据大小
int threshold:阈值,hashMap存放内容数量的临界点,当存放量大于这个值的时候,就需要将table进行扩张,新建一个两倍大的数组,并将老的元素移过去。threshold = (int)(capacity * loadFactor)
final float loadFactor:装载因子,在构造HashMap时指定,用来确定threshold
transient volatile int modCount:记录hashMap结构变化的次数,使用在hashMap的fail-fast机制中(当某个线程获取map的游标后,另一个线程对map做了结构修改的操作,那么原先准备遍历的线程会抛出ConcurrentModificationException异常)。这里注意volatile关键词,它代表modCount这个变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。
再来看HashMap的构造函数
构造函数1:
public HashMap(int initialCapacity, float loadFactor) { if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException("Illegal load factor: " + loadFactor); // Find a power of 2 >= initialCapacity int capacity = 1; while (capacity < initialCapacity) capacity <<= 1; this.loadFactor = loadFactor; threshold = (int)(capacity * loadFactor); table = new Entry[capacity]; init(); }看到注释了吗?capacity是初始容量,而不是initialCapacity,例如执行new HashMap(9,0.75);那么HashMap的初始容量是16,而不是9
构造函数2:
public HashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); }使用指定的初始容量,装载因子为DEFAULT_LOAD_FACTOR,调用构造函数1来完成
构造函数3:
public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); table = new Entry[DEFAULT_INITIAL_CAPACITY]; init(); }
初始容量和装载因子均为默认值
构造函数4:
public HashMap(Map<? extends K, ? extends V> m) { this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); putAllForCreate(m); }
从现有的map构造新的hashMap,初始容量用原map的容量和默认容量中大的那个值
下面让我们看看几个重要的功能实现
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; }
get函数通过输入key得到value,先通过hash,然后通过indexFor函数得到这个key在table的位置,再遍历链表得到结果
static int indexFor(int h, int length) { return h & (length-1); }
- [Java]JDK源码学习(3)HashMap
- JDK源码学习之HashMap
- java核心基础--jdk源码分析学习--HashMap
- JAVA源码学习-HashMap
- JAVA基础之HashMap源码(JDK 1.8)
- jdk 源码分析(1)java hashmap的结构
- JDK源码学习系列08----HashMap
- JDK源码学习之HashMap篇
- JDK源码学习之集合框架HashMap
- java源码解读之HashMap------jdk 1.7
- java源码学习之HashMap(一)
- JDK源码(一)HashSet、HashMap、Hashtable
- JDK源码-HashMap
- JDK源码之-HashMap
- JDK源码-HashMap
- 【jdk源码解析二】java.uti.HashMap源码解析
- [Java]JDK源码学习(2)Integer
- JDK源码学习之HashMap (一) : 底层存储结构分析
- 【Unix】Unix/Linux 实用技巧、箴言
- Windows 8将包含电话呼叫功能
- 数据库设计规范化的五个要求
- 最新的 PageValidate 类
- 2011-9-19 网络编程 晴
- [Java]JDK源码学习(3)HashMap
- 读取web.config中appSettings的key值
- Cassandra中rowcache的更新
- c# HttpWebRequest与HttpWebResponse 绝技
- 范凯:JavaEye为何被迫改名ITeye
- ajax
- 50个c/c++源代码网站(转自http://blog.chinaunix.net/space.php?uid=22830296&do=blog&id=1768388)
- 禁止android进去休眠状态
- JS对象之克隆