体系结构
①基本操作:
②遍历方式:
第一种: 键找值,通过map.keySet()获取Map的键集合,通过键去匹配Map中的值
Set<String> strings = map.keySet();
for (String string : strings) {
System.out.println(map.get(string));
}
第二种: 键值对,通过map.entrySet()获取Map的键值对对象集合,通过每次遍历集合使用getkey和getvalue获得键值
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
System.out.print(entry.getKey()+" :");
System.out.println(entry.getValue());
}
第三种: Lambda表达式
//匿名类方式
map.forEach(new BiConsumer<String, Integer>() {
@Override
public void accept(String s, Integer integer) {
System.out.print(s + " :");
System.out.println(integer);
}
});
//可简化
map.forEach((s ,integer) -> {
System.out.print(s + " :");
System.out.println(integer);
}
);
③Hashmap详解: 底层也是哈希表,但是比较的是键的hashcode
注:如果键存的是自定义对象,要重写hashcode和equals方法
HashMap源码解读:
m:表示方法,↑:表示重写的方法,->:表示继承,f:表示属性,I:表示接口,c:表示内部类
基础常量:
链表中的数据对象:
红黑树中的数据对象:
①首先创建一个HashMap
在底层什么也没做,只是设置一下加载因子0.75
②put增加一条数据,数组位置为null
第一个参数:调用hash方法并传key去计算出hashcode。第二,三个参数:键值。第四个参数:如果键重复了是否保留
开始添加数据的操作,首先是判断table是不是空的,是的话就去调用resize方法,如果是第一次put的话,resize方法就返回默认长度16
首先根据hashcode和数组的长度计算出应存入的index,再判断table[index]的值是否为空,如果是空表示此处无数据,调用newNode方法去创建一个键值对对象Node,放到数组当中
最后再比较当前数组的长度与扩容时机(16*0.75),如果小于就什么都不做
③put增加一条数据,数组位置不为null,且键不重复
如果计算出来的index所在的位置不为空,则执行else的语句。然后判断如果原来位置上的数据的hashcode与新数据的hashcode相同并且两个数据的键是否相同,如果不重复则:
先判断table上的元素是红黑树还是链表中的节点,如果是红黑树上的,则调用treeifBin方法去执行插入红黑树的操作。如果是链表上的元素,则先要判断数组上的元素是不是链表上最后一个元素,如果是就直接挂其后面,如果不是就要跟着链表往下找到最后一个元素再插入。
这里则是判断是否覆盖了元素,最后再return
④put增加一条数据,数组位置不为null,且键重复,则要覆盖
如果计算出来的index所在的位置不为空,则执行else的语句。然后判断如果原来位置上的数据的hashcode与新数据的hashcode相同并且两个数据的键是否相同,这里就等于跟链表或者红黑树中的第一个节点进行键比较
这里就要往链表或者红黑树下去逐个比较直至知道找到键相同的的那个元素并且比较内部的属性值,如果都是一样的就不进行写入,覆盖
这里则是判断是否覆盖了元素,最后再return