近日面试某著名公司,被问到java集合类中Set的实现原理,由于之前没有阅读过相关的源码,所以对与相关的实现原理不甚了解,于是开始尝试深入了解下。
在Java中, List、Map、Set是最经常用到的集合类。在其实现上,Set内部就是引用了Map,所以Set和Map本质上是一个样的。今天就来梳理一下Java集合类中的Map的一些知识。
上述的图片是引用网上的,这个是jdk中关于Map集合的一个类图,由图中可以看到,所有Map的实现类都继承Map接口,其中抽象类AbstractMap是Map接口的一部分实现,而Map的所有实现类都继承了AbsctractMap这个抽象类,所以在这里有必要对于AbstractMap的内部原理进行了解。
一. Map接口:
上图是Map接口里面所包含的所有方法,Map中常用的方法都在这里面声明,其中在Map接口里面还有一个接口Entry<K, V>。 顾名思义,Entry<K, V>是Map的一个入口,也就是说,Entry代表Map中的一个键值对,Map中的数据的存放形式都是通过Entry来进行的。其中Entry里面的方法有:
二:Abstractmap抽象类:
AbstractMap对于大部分Map中的方法进行了实现,其中多了两个变量:ketSet和values
其中keySet是key值的一个集合,values是value的一个集合,在方法keySet()中会把keySet变量返回,在values()中会会把values变量返回,其中keySet()方法的源码如下:
源码中我们可以看到,当调用keySet()时,会判断变量keySet是否为null, 如果是null,那么对于keySet进行初始化,如果已经初始化,那么直接返回,keySet的初始化是将其初始化为AbstractSet类的实例,其中AbstractSet也为抽象类,所以如果要进行抽象类的初始化,必须实现其中的抽象方法。初始化完成之后的keySet就拥有一下这些方法:iterator()、size()、isEmpty()等方法,其中size()、isEmpty()、clear()、contains()其中就是调用AbstractMap类本身的相应方法,iterator()返回的就是一个Iterator对象,Iterator是一个接口,所以在这里面提供了实现,这里的iterator遍历实际上是通过遍历EntrySet,然后通过EntrySet的遍历器获取相应的值。values()方法也类似,这里不再详述。
AbstractMap类里面的其他一些方法,如size(), isEmpty(),都是通过entrySet()方法获得Set<Entry<K, V>>对象,然后再进行处理。
在AbstractMap里面还提供了两个Entry的实现类,SimpleImmutableEntry和SimpleEntry,这里可以理解为javabean的形式,其中包含有两个属性,key和value和相应的get()、set()方法。这些在子类HashMap和LinkedHashMap中还会有更详细的介绍。
由于AbstractMap只提供了Map接口的通用的实现,对于不同的子类,相应的方法会有部分重载。文章中如有不恰当的地方,还请大家多多指教,第一次写博客,还是在学习中。