java源码解读之集合框架

    最近一段时间再补基础,因此看了一些源码。    其中自然是要看数据结构的,因此看了看java的集合框架,跟着网上的大牛。虽然大牛们已经写的十分的完善了,但是实践出真知,自己还是跟着大牛的思路去看看了看源码,原计划2天的空余时间看完的,没想到尽管只是看,没有深入理解都已经花了接近一周的时间。  为了方便自己理解记忆,特此开贴记录一下。

    先上图吧。

    

    没想到画这东西出来密密麻麻的我自己都惊讶了,可见前辈们付出了多少的心血在上面,才能有这么完善的体系。 

    说说自己的理解吧: 

                一:Iterator接口,其字面意思为 迭代器,事实上它却也是完成迭代的功能。通过Iterator接口与Collection联系起来。 也就是 Collection依赖于Iterator。因此,Collection及其子类都会依赖于Iterator,都能实现迭代的功能。

                二:我们平常常用的集合类有:  LinkList,ArrayList,不常用的有 :Vector及其子类Stack。  可以看到,我们平常能接触到的集合类都继承自AbstractList,AbstractList作为一个抽象类,通常帮我们完成了一个体系的骨架。   例如: 接口是对某一种功能的抽象,它通常只面向需求,例如需要什么,完成什么功能,达到什么效果等待。   而抽象类,或者说抽象基类,则会为完成该功能封装一些需要的东西,以及限定子类必须初始化什么东西,实现那些函数,保证抽象基类的子类被实例化后,能够形成一个健全的体系。(指从接口到抽象类,在到实例化的类中所有遇到的接口或者函数都被实现,完成某一种功能所必需的数据在实例化时就能被准备好。保证这一体系能够正常运行。)

                三:LinkList是基于链式存储,其内部有一个私有关键类: Node,节点的意思,作为链式成员,也负责前后联系。实现了Queue,Dequeue接口,可以用作队列,双端队列(应该也能作为栈,因为它们都是线性的,从这一点来说,应该Collection的子类都能作为队列,栈等数据结构操作。不知道对不对。)所以它的存取效率应该是较高的,但是查询的效率较低。(效率应该都是跟数据量挂钩的,平时数据量不够的话,效率一说可能感觉不太真实。)。  ArrayList是基于数组实现的,因此它的存取效率可能要低一点,因为他会判断容量是否够大,不够大就会进行相应的扩容,相应的就增加了执行的命令数,自然效率要低一些。   Vector的话也是基于数组实现,大部分内容跟ArrayList差不多,因为它们都继承自同一个抽象基类。 最主要的区别应该是它是线程安全的。

            四:Map跟Collection不存在上下级关系,或者说是同级关系更好理解一些吧。   以前一直在用,一直也存在一些疑惑。

另外一点想补充的就是Map,跟Collection都是接口,而我们更多的是将其看作为了类,因为我们常常在思考,collection的本质是什么,或者说Map的本质是什么。  因为我们经常听说它们,那么难免就越想越想不明白。    我的一点理解就是:它们并不是由什么什么构成,由什么什么实现,它们本质上只是一个接口,代表的是一组或者说一些功能的抽象,是一团方法的集合。我们去想它的本质是什么,这个就很尴尬了,因为它本身什么都没有。我们应该思考的是ArrayList或者说LinkList,Vector的本质是什么。   

                另外,Collection系,与Map系为什么说同级关系更好理解一些呢?  因为从表现形式上,Collection是基于一维的,是线性的关系,而Map是二维的,是平面的关系。即,key,value。    Map系之所以能够实现二维的数据存储,是通过泛型实现的。  而查看源码我们能比较明晰的看到,每一个泛型,K,V它们又都是属于Collection系的,能够实现特定的功能。但是其中的算法还是比较复杂的,HashMap,TreeMap的源码大概在4000行左右,除去空行跟注释应该也有2000多行的样子,它们各自的内部又定义了一系列的私有内部类,负责处理各自的逻辑。  HashTable则相当于Map的外甥吧,这样好理解一点,看图也能说明,其代码应该在1000行左右。 

                还有就是,Map接口中有一个Entry接口,这也是我们平时写循环语句: for(Map.Entry  e: ...)的由来,那么这个Entry是什么? 为什么Entry能够在一个Map里面遍历。   查看HashMap 的源码可以很容易知道:  有一个 Node内部类实现了Entry接口,这里的Node 跟LinkList里面的大同小异,都是节点的意思。   另外,HashMap有一个 成员变量,Node<K,V>[] table,这是一个Node型的数组,查看源码也能够发现,无论是put,还是set方法,都是在这二者做文章。       TreeMap类似。    因此Map不谈,只看HashMap的话,我们可以说其本质便是Node<K,V>。   至于为什么K会保证不重复,这里有一个忘了交代的了,那就是Set。

               五:Set接口能够保证一个不重复的集合。   从图中可以看到,Set接口继承自Collection,AbstractSet实现了Set接口,并且继承自AbstractCollection,(这也许就是传说中的多态吧)。查看Set接口,可以发现其没有新增的功能接口,最主要的是覆盖了几个父类的接口,并且提供了默认实现方法,大致是 Hashcode,equals,还有个啥记不得了。 但是这两个方法足以说明问题。  

        总结:通过这次的实践,进一步理解到基础的重要性。 同时对于我感觉算是一个惊喜的收获就是: 不要再对着接口抠破脑袋的去思考,它的本质是什么,它是如何实现之类的话题。  另外附上我们通信技术基础老师一句比较经典的台词:....人的一生只能研究一小点。 

阅读更多

没有更多推荐了,返回首页