Java集合HashMap的使用
特点
jdk1.2版本,线程不安全,运行效率快;允许使用null值作为key或者value。
存储结构
HashMap的存储结构为:数组+链表+红黑树(jdk1.8之后),添加红黑树的目的是为了提高效率。
基本使用
/**
* HashMap的使用
* 存储结构:数组+链表+红黑树(jdk1.8之后)
*
*@author :twb
*@version :1.8
* @// TODO: 2021/3/28
*/
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo1 {
public static void main(String[] args) {
Student s1 = new Student("孙悟空",100);
Student s2 = new Student("猪八戒",101);
Student s3 = new Student("沙僧",102);
Student s4 = new Student("唐僧",103);
HashMap<Student,String> hashMap = new HashMap<>();
//添加元素
hashMap.put(s1,"北京");
hashMap.put(s2,"上海");
hashMap.put(s3,"广州");
hashMap.put(s4,"湖南");
System.out.println("添加之后的元素个数为:"+hashMap.size());
System.out.println("添加之后的元素为:"+hashMap.toString());
//删除元素
// hashMap.remove(s1);
// hashMap.remove(new Student("猪八戒",101),"上海"); // 删除匿名对象时需要重写equals和hashcode方法
// System.out.println("删除之后的元素个数为:"+hashMap.size());
// System.out.println("删除之后的元素为:"+hashMap.toString());
//遍历元素
//1.keySet遍历
System.out.println("keySet遍历开始:");
Set keySets = hashMap.keySet();
for (Object keySet : keySets) {
System.out.println(keySet+"-->"+hashMap.get(keySet));
}
System.out.println("---------------------");
//2.entrySet遍历
System.out.println("entrySet遍历开始:");
Set<Map.Entry<Student,String>> entrySets = hashMap.entrySet();
for(Map.Entry<Student,String> entrtSet : entrySets){
System.out.println(entrtSet.getKey()+"-->"+entrtSet.getValue());
}
//判空
System.out.println(hashMap.isEmpty());//false
//判包含
System.out.println(hashMap.containsKey(new Student("唐僧",103))); //true
System.out.println(hashMap.containsValue("云南"));//false
}
}
源码分析
基本属性:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 hashmap默认初始容量的大小
static final int MAXIMUM_CAPACITY = 1 << 30; // hashmap数组的最大容量
static final float DEFAULT_LOAD_FACTOR = 0.75f; // 默认加载因子是0.75
static final int TREEIFY_THRESHOLD = 8; //jdk1.8 当链表长度大于8时,调整成为红黑树
static final int UNTREEIFY_THRESHOLD = 6;// jdk1.8 当链表长度小于6时,调整成链表
static final int MIN_TREEIFY_CAPACITY = 64;// jdk1.8 当链表长度大于8,并且集合元素个数>=64时,调整成为红黑树
transient Node<K,V>[] table;//hash表中的数组
transient int size;//元素个数
无参构造
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
put方法
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
总结
(1)HashMap刚创建时,table是null,其目的是为了节省空间,当添加第一个元素时,table的容量调整为16
(2)当元素个数>=阈值(16*0.75=12)时,会进行扩容,每次扩大为原来的两倍,目的是为了调整元素的个数
(3)jdk1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的是为了提高执行效率
(4)当链表长度小于6时,会调整为链表
(5)jdk1.8以前,链表插入元素的方式为头插法,1.8以后为尾插法