AbstractMap
AbstractMap
和AbstractList
,AbstractCollection
等抽象类类似,它实现了Map
接口的部分方法,提供了一些基础的实现,我们耳熟能详的HashMap
, TreeMap
, ConcurrentHashMap
都是他的子类。
构造
AbstractMap
提供了一个protected
修饰的无参构造方法,意味着只有它的子类才能访问(当然它本身就是一个抽象类,其他类也不能直接对其实例化),也就是说只有它的子类才能调用这个无参的构造方法。
源码分析
可以看出AbstractMap
提供了一些基础方法的实现,用于到增加/修改元素的put()
和putAll()
,用于删除元素的remove()
和clear()
,以及其他的一些用于判断或者获取这个Map的属性的一些方法。其中需要注意的是,put()
和putAll()
子类必须重写,因为这里的实现仅仅是抛出一个异常,如果子类不进行重写,调用该方法就会抛出一个异常。
通过源码我们不难看出,这个类的方法基本是都是通过Entry
这个对象来完成的,而获取这个对象的方法是entrySet()
这里的entrySet()
方法却是一个抽象方法,具体的实现需要子类来完成,这是很典型的设计模式中的模板方法模式,那么何为模板方法模式呢?其实很好理解,就是在一个方法中定义一个算法的骨架,而将一些步骤的实现延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中某些步骤的具体实现。这里因为entrySet()
在AbstractMap
中并未实现,而是交给了它的子类去完成,但是对于该类中的方法却可以对它进行一个“算法骨架” 实现,这就是模板方法模式。
还有两个我们经常会用到的视图属性
这两个视图分别是用于键构成的集合keySet
以及值构成的集合values
,在JDK 8 中将volatile
的关键字给去掉了,不知道为毛,有知道的朋友可以私信我,我给添上~
下面来看看怎么获取这两个视图:
可以看出,实际上它的实现是通过一个AbstractSet
的匿名内部类,而该内部类的迭代器实际上就是该entrySet()
的迭代器(没错,是它是它,就是它,我们的英雄小哪吒~),只不过在next()
的时候调用了getKey()
,而其他方法的实现都是调用了AbstractMap
的中的方法,而values()
方法的实现也与这个差不多,大家可以自己去源码中看一下,这里就不多占篇幅去说了。
两个内部类
没错,就是这两个货SimpleEntry
和SimpleImmutableEntry
,他们都实现了Entry
接口,那么问题来了,他们为什么是两个呢,因为从这个图上看,这俩货是一样的。。其实区别就在于setValue()
这个方法。
可以看出,这两个类一个是可以修改的(SimpleEntry
),而另一个是不能修改(SimpleImmutableEntry
)的。这就是他们的区别所在。
视图是个啥
这节课,我们频繁的提到了一个词———集合视图,集合视图是什么?
简单的来说,就是有一定限制(只读,同步,受查,只能删除不能增加等等)的集合类,被限制的是视图,而不是集合,比如*.subList()
,Map.keySet()
,Map.values()
,Map.entrySet()
,Arrays.asList()
这些都是集合视图,其实就是对原集合的一层包装 ,不同的集合视图有不同的用途,有的是只读有的是同步的。针对视图的操作会影响到集合的数据。
原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。