Map集合(双列集合)(夫妻对集合)
map的key值是无序的,不可重复的,用Set集合存储
value值是无序的,可重复的,用Collection集合存储
key-value存放在Entry类中,Entry类是无序的,不可重复的,用Set集合存储
1.HashMap
map接口下最常用的实现类,是线程不安全的,效率高。
底层存储数据的结构:数组+链表+红黑树(jdk1.8)
存储过程:
Map<String,String> map = new HashMap<>();
map.put("key","value");
以上面的代码为例,
首先会通过调用key的hashCode()方法得到哈希值,通过HashMap中的指定算法和哈希值进行运算得到值,这个值是要存放的索引位置。
如果该索引位置不存在值,则将此数据存放在这个位置上。
如果存在值,比较它们的哈希值,如果相同,则不能存放
如果不同,通过equals()方法进行比较。如果返回true,则不能存放。
如果返回false,则以链表的方式存放在这个位置上。
扩容机制:
如果是用无参构造创建的对象,这时创建的是一个长度为0的数组,当调用put()方法后,会创建一个长度为16的数组。(JDK1.8)
在JDK1.7以前,会直接创建一个长度为16的数组。
HashMap是根据源码中的常量(threshold临界值)进行扩容的。
源码:
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY)
newThr = oldThr << 1; // double threshold
当该数组的长度大于临界值(填充因子*容量)时,扩容为原来长度的2倍。
如果当前数组的某个索引上的元素以链表的形式存在的数据长度>8且数组的长度大于64,以后存入的所有数据改用红黑树存储。
2.LinkedHashMap(HashMap的子类)
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的基础上添加了两个指向。before和after。
与前后数据连接起来了,适合频繁删除和插入的操作
3.TreeMap
能排序的Map。
去重原理和HashMap不同。
HashMap是通过hashCode()和equals()实现去重。
TreeMap是通过比较器(Comparable、Comparator)实现去重,返回的值为0,则代表是同一个对象。
存放在TreeMap中的对象都必须实现Comparable或Comparator接口,否则会报错
注意:
以上去重,都是基于key值进行比较的。