Map接口:
存储双列数据:存储key–value对(键值对)数据,类似于数学中函数的概念
Map接口的实现类:
- HashMap,LinkedHashMap(是HashMap的子类)
- TreeMap
- Hashtable,Properties(是Hashtable的子类)
实现类之间的关系:
- HashMap作为Map的主要实现类,线程不安全,效率高,可以存储null的key和value(两个都可以是null)
- Hashtable作为Map的古老实现类,线程安全,效率低,不可以存储null的key和value(只要有一个是null就不可以),会报空指针异常。基本不使用
注意:和ArrayList一样,即使涉及到了多线程问题,也不会因为Hashtable是安全的,而使用它,而是用Collections工具类的相关方法把HashMap变成线程安全的
public static void main(String[] args) {
Map map=new HashMap();
map.put(null,null);
map.put(null,123);
}
- LinkedHashMap在HashMap的基础上增加了一对指针,指向前一个存放的,和后一个存放的元素,保证在遍历map元素时,可以按照添加的先后顺序实现遍历。对于频繁的遍历操作,效率高于HashMap。如果有频繁的遍历,一般使用此类
- TreeMap:可以保证根据添加的key–value对进行排序,实现排序遍历,是按照key来排序的,此时考虑key的自然排序或定制排序,底层使用的是红黑树
- Properties: 常用来处理配置文件,key和value都是String类型
HashMap的底层:
最初的时候是数组加链表(JDK7及之前)
数组+链表+红黑树(JDK8),加红黑树是为了提高效率
Map结构的理解
Map中存储的key-value特点:
value可以重复,key不能重复,并且key还是无序的,key就相当于是用Set存储的,保证无序,不可重复性。
因为key是无序的,key对应value,所以value也不可能有序,value的特点是可重复的,无序的,也没有一种专门的结构去存储这种类型的数据,就泛泛的称作用Collection去存储
事实上,Map中放的是一个一个数据,是一个一个的Entry,是这个Entry当中有两个属性一个叫做key,一个叫做value,实际上调用put方法的时候,put的是一个一个的Entry,添加的其实是Entry对象
因为key没有顺序所以Entry对象也是没有顺序的,key不相同,所以Entry不可重复
Entry的特点:不可重复,无序的,可以理解为用Set承装
Map中的key:无序的,不可重复的,使用Set存储所有的key,到底是什么Set就看Map是什么Map了,如果是HashMap就是HashSet去存key,如果是linkedHashMap就用LinkedHashSet存储
Map中的value:无序的,可重复的,使用Collection存储所有的value,它所在的类不用重写hashCode,重写equals即可。本质上来说它不用重写hashCode的原因:hashCode主要涉及到存的时候效率高一些,找的时候方便一点,value因为封装在Entry当中,找value先去找它的Entry的key
一个键值对key–value构成了一个Entry对象
Map中的Entry:无序的,不可重复的,使用Set存储所有的Entry,不可添加重复数据
key完全有可能是我们自定义的类,为了保证无序性,不可重复性,要求key所在的类要重写equals方法和hashCode方法(这是以HashMap为例的说的,如果是TreeMap就不用管equals方法和hashCode方法了,涉及到自然排序和定制排序了,判断标准就不一样了)
以HashMap为例,containsKey(Object key):是看当前的Map中有没有这个key
判断过程,是先去调用hashCode方法,找到那个位置,再调用equals才知道包不包含这个key
containsValue():用来判断有没有指定的Value