Map
存储任意键值对(key-value)
键:无序,无下标,不允许重复(唯一)
值:无序,无下标,允许重复
Map接口下常见实现类
- HashMap
- linkedHashMap
- TreeMap
- HashTable
- Properties
HashMap
作为Map的主要实现类
线程不安全,效率高
底层结构:哈希表(数组(Node[])+链表+(jdk1.8)红黑树)
可以存储值为null的key和value
结构分析
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // HashMap初始容量大小位运算得到16
static final int MAXIMUM_CAPACITY = 1 << 30;// HashMap 最大容量
static final float DEFAULT_LOAD_FACTOR = 0.75f;// 默认加载因子
static final int TREEIFY_THRESHOLD = 8;// 阈值,当链表长度为8时,调整为红黑树(jdk1.8)
static final int UNTREEIFY_THRESHOLD = 6;// 阈值,当链表长度为6时,调整为链表(jdk1.8)
// 当链表长度大于 8 且元素集合个数大于64时,调整为红黑树
static final int MIN_TREEIFY_CAPACITY = 64;
transient Node<K,V>[] table;// 哈希表中的数组
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);
}
过程分析:
//jdk1.7底层创建了长度是16的一维数组Entry[] table。
//jdk1.8 Node[] table 为 null
HashMap hashMap = new HashMap();
首次调用put()方法时,容量调整为16
添加元素:
(1)调用hashcode()方法计算key的hash值,此hash值再通过某种算法得到存放在数组中的位置,若该位置为空,key-value添加成功,若有值
(2)再比较key的hash值,如果hash值不同,key-value添加成功形成链表,若相同
(3)调用equals()方法,返回false,key-value添加成功,返回true,替换原有的key-value
添加过中的扩容问题:
在添加过程中,如果元素达到元素个数的阈值(16 * 0.75 = 12)时,会进行扩容为原来的2倍。(为了减少调整元素的个数)
jdk1.8 链表与红黑树的关系
当链表长度大于 8 时,且数组的元素个数大于64,会调整为红黑树。(为了提高效率)
当红黑树节点数量小于 6 时,调整为链表
链表的结构规则(七上八下)
jdk7:新的元素指向旧的元素
jdk8:旧的元素指向新的元素
LinkedHashMap
保证在遍历map元素时,可以照添加的顺序实现遍历
原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
对于频繁的遍历操作,此类执行效率高于HashMap。
LinkedHashMap底层使用的结构与HashMap相同,因为LinkedHashMap继承于HashMap.
区别就在于:LinkedHashMap内部提供了Entry,替换HashMap中的Node.
//LinkedHashMap中的内部类:Entry
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
//HashMap中的内部类:
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
TreeMap
保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
底层使用红黑树
向TreeMap中添加key-value,要求key必须是由同一个类创建的对象m,因为要照key进行排序:自然排序 、定制排序
HashTable
古老的实现类
线程安全的,效率低
不能存储null的key和value
Properties
常用来处理配置文件。key和value都是String类型