HashMap原理解析
用了好久的HashMap呀,但是一直都是只会用而已,根本就不太懂里面是啥 怎么实现的... 最近终于稍微深入了解了一下 。
1.首先我们来讲一下 HashMap的基本使用:存储数据 与 获取数据
>>>创建map
HashMap<String,String> map = new HashMap<String,String>();
>>>存储数据
map.put("name","zhangsan");
map.put("age", "18");
map.put("sex", "male");
>>>获取数据方式1 通过keyset遍历
Iterator iterator = map.keySet().iterator();
while(iterator.hasNext()){
String key = (String) iterator.next();
String value = map.get(key);
System.out.println("KeySet遍历:key="+key+",value="+value);
}
>>>获取数据方式2 通过entryset遍历
Iterator entryIterator = map.entrySet().iterator();
while(entryIterator.hasNext()){
Entry entry = (Entry) entryIterator.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue();
System.out.println("EntrySet遍历:key="+key+",value="+value);
}
***遍历方式 keyset 与 entryset 的比较
keySet: 通过 next()方法获取到map的key,然后再通过 map.get(key) 获取对应的value值 (存到Set集合里面的只是map集合的 key)
entrySet: 通过 next()方法得到 Entry对象,通过entry.getKey(), entry.getValue() 分别就能获取到对应的值 (存到Set集合里面的是 Entry对象,包含集合的 key,value)
综合来说: entrySet 比 keySet遍历方式更高效些,建议使用 方式2 entrySet 遍历map集合。
HashMap使用代码示例: HashMapApp.java
package com.study.thread.juc_thread.base; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; public class HashMapApp { public static void main(String[] args) { //创建map HashMap<String,String> map = new HashMap<String,String>(); //存储数据 map.put("name","zhangsan"); map.put("age", "18"); map.put("sex", "male"); //获取数据方式1 通过keyset遍历 Iterator iterator = map.keySet().iterator(); while(iterator.hasNext()){ String key = (String) iterator.next(); String value = map.get(key); System.out.println("KeySet遍历:key="+key+",value="+value); } System.out.println("---------------遍历方式分割线------------------"); //获取数据方式2 通过entryset遍历 Iterator entryIterator = map.entrySet().iterator(); while(entryIterator.hasNext()){ Entry entry = (Entry) entryIterator.next(); String key = (String) entry.getKey(); String value = (String) entry.getValue(); System.out.println("EntrySet遍历:key="+key+",value="+value); } } }
2. 接下来我们来看 HashMap的初始化 ,也就是创建map对象
默认的容量值为: 16
默认的负载因子: 0.75
容量: 即map集合的初始化大小,之后会根据存储对象多少以及 负载因子的值来进行扩容
负载因子: 即当map集合存储的数据超过容量的 0.75时,可能会发生扩容操作
例如: 容量为 16 ,负载因子为 0.75 , 当存储数据量大于12,发生hash冲突,且每个map的数组中每个bucket下都已有值了,则会发生扩容 (大小变为原来集合的 2倍)
***推荐指定容量创建map,因为扩容会很消耗资源。 初始容量值 = (需要存储的对象 / 负载因子) +1
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); this.loadFactor = loadFactor; this.threshold = tableSizeFor(initialCapacity); } /** 指定初始化容量值 */ public HashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } /** 无参的构造方法 */ public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted } /** 指定map */ public HashMap(Map<? extends K, ? extends V> m) { this.loadFactor = DEFAULT_LOAD_FACTOR; putMapEntries(m, false); }
3.然后我们来看一下HashMap如何存储数据,这里我们就需要了解HashMap的数据结构了(如何解决hash冲突)。
数组+链表 、 红黑树 hashcode方法 ....
待更新....
4.最后我们来看一下HashMap如何获取数据。