Java中HashMap机制和原理个人总结
原理:
- HashMap是以key-Value(键值)对的方式来存储数据,存储在节点中,数据类型为Node;
- HashMap的方法没有实现同步,所以线程是不安全的;
- HashMap的存储机制也是节点数组+单向链表;
- key不允许重复,可以理解为人的身份证,具有唯一性, key可以为null,但是只能一次,key的数据类型一般为字符串类型,便于比较,使得每个都不同;
- Value允许重复,相当于人的名字,可以为多个null;
- 一个key对应一个Value;
- HashMap与HashSet的最大区别就在当key一样时,新Value值会覆盖之前的key的Value;
- 为了方便遍历HashMap,所以在HashMap中有个entrySet用来保存HashMap的kv数据,其实是对HashMap数据的引用,并没有真正存储数据,用getKey方法调用key,用getValue方法调用Value;
- 在HashMap中还有专门存储key的set集合KeySet;
- 在HashMap中有专门存储Value的集合Values ;
- HashMap中的数组数据类型是Node类并实现了Map中的Entry类,所以entrySet集合里面存储的是Entry的类型数据,将Node类包装成Entry的类型数据,但是只是引用!!!;
图示:

- 链表形成的条件:1.hash值相等;2.不是同一对象;3.key不相等;4.key不为空。
- HashMapNode数组第一次扩容是16个大小Node,但是有一个加载因子0.75,具有临界值(threshold)16*0.75=12,当数组存储的元素到达12个节点时,就会自动扩容table数组为原来的2倍,临界值也会跟着扩容2倍。
- 如果一条链表的元素超过8个且table节点数组的大小>=64个,这条链表就会进行树化,
重点:如果一条链表元素超过8个,但是table节点数据的大小没到达64个,这时候table就会进行resize(扩容)
例:假如table此时为16个,一条链表超过8个,并再增加一个链表元素,第一次table扩容2倍,变成32个,这时候如果再增加一个链表元素,这时候table扩容2倍,变成64个,这时候如果再增加一个链表元素,这次数组table不会再扩容,这时候这个链表就会变成红黑树(TreeNode),当这个红黑树删除节点至小于8个后,就会重新转化成链表,这个过程叫做剪枝。
链表红黑树树化过程代码举例:
public class Demo {
public static void main(String[] args) {
HashMap hashMap = new HashMap();
for (int i = 0; i <8 ; i++) {
hashMap.put(new A("s"),100);
}
hashMap.put(new A("s"),100);
hashMap.put(new A("s"),100);
hashMap.put(new A("s"),100);
System.out.println(hashMap);
}
}
class A{
private String name;
public A(String name) {
this.name = name;
}
@Override
public int hashCode() {
return 100;
}
}
- HashMap遍历形式举例:
public class Demo {
@SuppressWarnings("all")
public static void main(String[] args) {
Map haMa = new HashMap();
haMa.put("no1","ssss");
haMa.put("no4","swx");
haMa.put("no8","gsdsd");
haMa.put("no13","gsds");
haMa.put("no1222","sddsg");
Set set = haMa.keySet();
for (Object key:set) {
System.out.println(key + "-"+haMa.get(key));
}
System.out.println();
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
System.out.println(key + "-"+haMa.get(key));
}
System.out.println();
Collection v1 = haMa.values();
for (Object value:
v1) {
System.out.println(value);
}
System.out.println();
Iterator iterator1 = v1.iterator();
while (iterator1.hasNext()) {
Object value = iterator1.next();
System.out.println(value);
}
System.out.println();
Set set1 = haMa.entrySet();
for (Object entry:set1
) {
Map.Entry en = (Map.Entry) entry;
System.out.println(en.getKey()+"-"+en.getValue());
}
System.out.println();
Iterator iterator2 = set1.iterator();
while (iterator2.hasNext()) {
Object entry = iterator2.next();
Map.Entry en = (Map.Entry) entry;
System.out.println(en.getKey()+"-"+en.getValue());
}
}
}