Map接口
Map(接口)
java.util.Map
Map是一个接口, 一般使用的是Key-Value键值对的形式存储数据, 且key不能重复,如果重复值会被覆盖
特点:
- 可以根据键 提取对应的值
- key键不允许重复,如果重复值会被覆盖
- 存放的都是无序数据
- 初始容量是16,默认的加载因子是0.75
注意事项:
- 给定一个键和一个值,你可以将该值存储在一个Map对象. 之后,你可以通过键来访问对应的值。
- 当访问的值不存在的时候,方法就会抛出一个
NoSuchElementException
异常. - 当对象的类型和Map里元素类型不兼容的时候,就会抛出一个
ClassCastException
异常。 - 当在不允许使用Null对象的Map中使用Null对象,会抛出一个
NullPointerException
异常。 - 当尝试修改一个只读的Map时,会抛出一个
UnsupportedOperationException
异常。
关系图:
HashMap(实现类)
HashMap的键要同时重写hashCode()和equals().
基于哈希表的 Map
接口的实现。此实现提供所有可选的映射操作,并允许使用 null
值和 null
键。
特点: 无序, key不能重复
原理
HashMap底层是一个Entry数组(默认大小为16),当存放数据时会根据hash算法计算数据的存放位置。算法:hash(key)%n,n就是数组的长度。
当计算的位置没有数据时,就直接存放,当计算的位置有数据时也就是发生hash冲突的时候/hash碰撞时,采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。
这使得HashMap的查询效率非常高
实现原理图:
**Entry数组的初始容量是16. 加载因子是0.75(上限率). 当map中的元素碰撞率>16*0.75时, 会进行扩容, 一般是扩容当前数组大小的2倍 ( 底层使用的移位算法 ) **
碰撞率 > 当前数组长度*0.75时, 会进行扩容
碰撞率: 发生碰撞元素个数 / 当前数组大小
例如: 两个元素使用的同一个下标时, 碰撞个数就是2
常用构造
方法 | 说明 |
---|---|
HashMap<K, V>() | 无参构造(K和V均为泛型) |
常用方法(Map接口中的方法)
Map<K, V>
返回值 | 方法 | 说明 |
---|---|---|
V | put(K key, V value) | 添加键值对, 并返回value |
V | get(Object key) | 根据key获取指定的value |
void | clear(); | 清空Map所有的键值对 |
V | remove(Object key) | 删除指定key对应的键值对并返回其value |
boolean | isEmpty() | 是否为空 |
int | size() | 键值对的个数 |
boolean | containsKey(Object key) | 是否包含指定key |
boolean | containsKey(Object key) | 是否包含指定的Value |
boolean | equals(Object obj) | 比较和其他Map是否相等 |
int | hashCode() | 获取Map在内存中对应的哈希值 |
Collection |
values(); | 把map中所有的value存到一个集合中并返回这个集合 |
Set |
keySet() | 把Map中的所有key存到一个Set集合中, 并返回. 参见: keySet()实例 |
Set<Map.Entry<K, V>> | entrySet() | 把Map中的所有键值对(Entry对象)存入Set集合. 参见: entrySet()实例 |
keySet()实例:
// 定义map...
Set<Integer> set = map.keySet();
for (Integer i : set) {
System.out.println(i);
}
entrySet()实例:
java.util.Map.Entry
是一个键值对对象, 可以使用getKey()
和getValue()
获取key和value
// 定义map...
Set<Entry<Integer, String>> set2 = map.entrySet();
for (Entry<Integer, String> entry : set2) {
System.out.println(entry.getKey() + " : " + entry.getValue());
}