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的基础上添加了两个指向。beforeafter

与前后数据连接起来了,适合频繁删除插入的操作

3.TreeMap

能排序的Map。

去重原理和HashMap不同。

HashMap是通过hashCode()和equals()实现去重。

TreeMap是通过比较器(Comparable、Comparator)实现去重,返回的值为0,则代表是同一个对象。

存放在TreeMap中的对象都必须实现Comparable或Comparator接口,否则会报错

注意:

以上去重,都是基于key值进行比较的。