Map
Map接口中存储的是key(键)和value(值),由键值对组成的。每一个键都不重复。值是可以重复的。
key-value称之为键值对
将每一个键值对看作一个对象,抽取出一个代表键值对的类,叫做Map.Entry
//创建一个映射
Map<String,String> map = new HashMap<>();
//添加数据
map.put("温人豪"(key),"是谁"(value));
//根据key获取value,获取key值不存在返回null
sout(map.get("温人豪"))
//根据key移除元素
map.remove("温人豪")
//判断key是否存在
map.containKey("温人豪")
//判断values是否存在
map.containsValue("是谁")
//清空map
map.clear();
//获取元素个数
map.size();
//获取所有的value
Collection<String> values = map.values();
//获取所有的key
1) Set<String> strings = map.keySet();
2) for (String key : strings){
sout(key);//获取键
sout(map.get(key));//获取值
}
// 获取所有键值对
1)Set<Map.Entry<String,String>> entries = map.entrySet();
sout(entries)
2) for (Map.Entry<String,String> entry : entries){
sout(entry);
sout(entry.getKey());
sout(entry.getValue());
}
//快速遍历map
map.forEach((key,value) -> System.out.println(key + ":"+value));
//判断map是否为空
sout(map.isEmpty());
map 使用方法的练习
输入一个字符串,统计每一个字符出现的次数 aaabbccdd
最初想法:先设置一个空的map,从左到右依次遍历,这些值是是键值对中的值,出现的次数是键值对中的键、从第一个开始,并与map中的键比较,如果没有则创立一个新的键,如果有,则在值处加1,
HashMap
- key和value 允许 null
- 是线程不安全的映射
- 输出的内容是无序的,位置可能发生改变
- 当第一次put元素时,会创建一个长度为16的Node类型的数组,默认的阈值是12,默认的初始容量是16,默认的加载因子是0.75
- 初始化容量是2的n次方的形式
- 底层是数组+链表+红黑树
- 默认扩容是容量翻一倍
HashMap() : 创建一个空的HashMap
HashMap(int initialCapacity) : 指定初始容量,初始容量一定是2的n次方的形式
HashMap(int initialcapacity,float loadFactor) : 使用指定的初始容量和加载因子构造一个空HashMap。
源码总结:
- 如果链表长度大于8,数组长度小于64,或者大于默认阈值12。数组会进行一次扩容。数组长度翻倍,并且对数据重新进行高低位分配。链表的长度会减少。数组长度大于64,链表长度大于8会转为红黑树
- HashMap初始化容量永远都是2的n次方格式
- 扩容时是容量范围,如果原来的桶上是链表,那么扩容后要么放在原来的索引处,要么是原来索引位置+原来的数组长度处
- 当扩容时,如果桶上是一个红黑树,经过运算长度小于等于6,会变成链表。
- hashMap的key一般不要使用自定义类型,如果要使用,重写hashCode方法。
自定义类型是根据地址为判断依据,如果存两个数值一样的数,并不会有问题。应该改成属性值相同,地址不同认为是一个。需要重写equals,Objects的equals默认判断的是两个地址值,需要改成属性相同就返回true。
断点
打断点之后点debug,程序会运行到打断点的前一行,打断点的那一行还没有执行
快捷键
F8:程序往下执行一行后停止
F9:直接跳过没有打断点的代码,跳到打断点的代码处停止
hash碰撞的情况
- key的值相同,key的hash一样,把新的值替换为旧的值
hashMap.put("1",1000);
hashMap.put("1",2000);
- key值不同,hash值相同。会对桶中的结点一个一个比较,直到链表结点的next是两个不同的next是null,key会被映射到哈希表的同一个位置,也就是同一个“桶”中
hashMap("Ma",3000)
hashMap("NB",4000)
- key值不同,hash值不同。(n-1)&hash后的值相同。这两个不同的key会被放置在同一个桶中的链表或红黑树上
hashMap.put("a",5000);
hashMap.put("b",5000);
hashMap.put("c",5000);
hashMap.put("d",5000);
hashMap.put("e",5000);
hashMap.put("aerg",5000);
hashMap.put("agr",5000);
hashMap.put("aeweg",5000);
hashMap.put("aarg",5000);
Hashtable
- Hashtable的key和value不能是null,如果是null,抛出空指针异常。
- 线程是安全的
- 默认初始容量是11,默认加载因子是0.75
- 指定的初始化容量指定多少就是多少
- 默认扩容是先扩大一倍再加1