Java集合源码分析

来源:互联网 发布:deepin 安装软件 编辑:程序博客网 时间:2024/06/05 17:53
*本文主要介绍集合底层的存储结构和开发过程中出现频率较高的方法
*集合框架图(该图为简略图,主要分析以下六个常用的实现类)

框架简略图

List- - ->ArrayList
ArrayList类内部的属性和方法:  private transient Object[] elementData;//临时数组  private static final int DEFAULT_CAPACITY = 10;//缺省容量为10  private static final Object[] EMPTY_ELEMENTDATA = {};//空数组  当使用无参构造new对象时:new ArrayList();    构造方法内部:this.elementData = EMPTY_ELEMENTDATA;    即:Object[] elementData = {};一个标准数组  数组容量扩容机制:    '''java        private void grow(int minCapacity) {            int oldCapacity = elementData.length;            int newCapacity = oldCapacity + (oldCapacity >> 1);//新的容量值为旧容量值的1.5倍。            if (newCapacity - minCapacity < 0)                newCapacity = minCapacity;            if (newCapacity - MAX_ARRAY_SIZE > 0)                newCapacity = hugeCapacity(minCapacity);            elementData = Arrays.copyOf(elementData, newCapacity);//数组重构        }    '''  最后通过:elementData = Arrays.copyOf(elementData, newCapacity);进行数组重构。常用方法:        1. add(E e);//将指定的元素添加到此列表的尾部。        2. addAll(Collection<? extends E> c);//将该 collection 中的所有元素添加到此列表的尾部。        3. get(int index) ;//返回此列表中指定位置上的元素。        4. size() ;//返回此列表中的元素数。        5. toArray() ;//按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。        6. remove(int index);//移除此列表中指定位置上的元素    综合分析:        由于ArrayList的数据结构是基于动态的数组,每次添加,删除元素时,都要进行数据拷贝,重构数组,因此做 增删 操作时开销较大,效率低下。        在做修改,查询操作时,可以由数组下标,快速定位获取元素,所以效率高。

List- - ->LinkedList
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
链表结构图:
链表结构图
链表详解:http://blog.csdn.net/hackbuteer1/article/details/6591486/
链表方法详解:http://blog.csdn.net/i_lovefish/article/details/8042883
源码分析:
这里写图片描述
从图中可以看到,LinkedList的增删操作,仅仅是创建一个节点,并将节点的指针存储在前一个节点和后一个节点的指针域内。相比ArrayList的重构数组,开销较小,效率略高。
做修改,查询操作时,需要通过指针遍历整个链表,来确定元素的位置,若是数据庞大,则效率及其低下。
综合分析:LinkedList特点:增删快,改查慢。
以下为测试结果:
这里写图片描述

Set - - ->HashSet
HestSet是通过HashMap实现的,底层是由数组和链表组成的数据结构
这里写图片描述
再看源码:
这里写图片描述
(1)通过key值获取hash值,而hash值是用来定位hash表索引的
(2)hash表的一个索引处存放的是一张链表的指针,循环遍历链表上的每一个对象才可以定位到键值对应的Entry
(3)put时,如果hash表中没有定位到,就会计算哈希值,并创建Entry最终保存到table[i]中(数组中),如果定位到了,则更换Entry中的value,并返回旧value.
(4)因为hash值的不确定性,最终hashset中的数据是无序的。
(5)看源码,允许存储null值。
综合分析:HashSet特点:无序,唯一。

Set - - -> TreeSet
TreeSet:是通过TreeMap实现的。而TreeMap基于红黑树实现的。
红黑树数据结构:
这里写图片描述
源码分析:
这里写图片描述
综合分析:TreeSet集合特点:有序,唯一。

Map - - - > HashMap
通过上面源码可知
(1)允许null键,null值。
(2)集合无序。
(3)key键唯一,值可以重复。key对应的类需要重写hasCode和equals()方法。
(4)底层数据结构:链表数组
Map - - - > TreeMap
通过上面源码可知
(1)通过实现Comparable 接口和设置选择器来确保 key的唯一性。
(2)通过二叉树实现元素的有序性。

相关博客:http://blog.csdn.net/chenssy/article/category/1688799