ArrayList和LinkedList源码阅读笔记
来源:互联网 发布:百度语音软件 编辑:程序博客网 时间:2024/04/27 21:20
List 接口继承自Collection接口,并在Collection接口的基础上添加了大量的方法,使得可以在List 的中间插入和删除元素。
List 按照插入的顺序来保存元素,它常用的实现类主要有两种:ArrayList和LinkedList,其中ArrayList 擅长随机访问元素操作,但是在中间插入和存取元素时比较慢;而LinkedList在中间进行插入和删除的操作比较快,随机访问方面相对较慢。只要阅读以下这两个类的底层实现方式,就很容易理解它们各自的优势。
ArrayList:
ArrayList 的列表对象实质是存放在一个引用型的数组内,并通过不断的改变该引用型数组的指向来改变数组的容量。
ArrayList 类内部:
private transient Object[] element;//存放列表对象的数组的引用,private int size; //用来记录列表中实际对象的数量;同时还引入Capacity,用来不断调整存放对象的数组的大小。
ArrayList 随机访问元素:
因为底层是通过Object类型的数组实现,所以可以直接通过数组下标来访问任何元素。
ArrayList中间插入和删除元素:
public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData,index, elementData, index + 1, size - index); elementData[index] = element; size++; }
可以看出,当向ArrayList的index位置中插入元素时,包括index以后的所有元素都要向后移动一位,需要进行很多的赋值操作,所以ArrayList在中间插入和删除代价较大。
当向ArrayList增加元素时,必须保证数组的容量能够确保这个元素还能再加进去。这时候如果数组的size与capacity的值一样,就必须增大capacity的值,使add操作能顺利进行。ArrayList 通过下面方法实现自动改变数组大小机制:
private void ensureCapacityInternal(intminCapacity) { modCount++; // add 方法前面通常会有ensureCapacityInternal(size + 1),当size + 1的值比数组容量的值小时,则不做任何操作,当size + 1的值比数组容量的值大时,则要扩大数组的容量。 if (minCapacity - elementData.length> 0) grow(minCapacity);} private staticfinal int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;private voidgrow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity +(oldCapacity >> 1); if (newCapacity - minCapacity< 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE> 0) newCapacity = hugeCapacity(minCapacity); //这步操作是关键,通过改变elementData的引用来实现数组容量的自动改变机制。 element = Arrays.copyOf(elementData, newCapacity); } private static int hugeCapacity(intminCapacity) { if (minCapacity < 0) //overflow throw newOutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE)? Integer.MAX_VALUE : MAX_ARRAY_SIZE;}
通过以上代码,我们可知java自动增加ArrayList大小的思路是:向ArrayList添加对象时,原对象数目加1后如果大于数组长度,则建一个适当长度的新数组,并将原数组的内容进行拷贝,然后让element对这个新数组进行引用。原数组会自动抛弃(java垃圾回收机制会自动回收)。
LinkedList:
LinkedList内部定义了Node类型的结点,其中包括列表对象的值,以及前一个结点和后一个结点的引用
private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E>next) { this.item = element; this.next = next; this.prev = prev; }}
LinkedList 通过Node<E> first,Node<E> last两个属性用来标记该链表的首结点和尾结点。
LinkedList 在中间增加和删除元素:
LinkedList 找到index所在位置的结点,然后通过改变该位置结点的prev和next 的引用来进行插入和删除操作。
public void add(intindex, E element) { checkPositionIndex(index); if (index == size) linkLast(element); else linkBefore(element, node(index)); } void linkBefore(E e, Node<E>succ) { // assert succ != null; final Node<E> pred = succ.prev; final Node<E> newNode = newNode<>(pred, e, succ); succ.prev = newNode; if (pred == null) first = newNode; else pred.next = newNode; size++; modCount++;}
LinkedList随机查找的操作:
public E get(intindex) { checkElementIndex(index); return node(index).item;} Node<E> node(int index) { if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
如果index比size/2小,就从前往后找,如果index比size/2大,就从后往前找。虽然对查找进行了一定的优化,但是查找时间级别仍是O(n),而ArrayList随机访问的时间是O(1)。
- ArrayList和LinkedList源码阅读笔记
- LinkedList源码阅读笔记
- LinkedList源码阅读笔记
- JDK源码阅读——ArrayList\LinkedList
- ArrayList源码阅读笔记
- ArrayList源码阅读笔记
- ArrayList源码阅读笔记
- ArrayList和linkedList源码分析
- LinkedList和ArrayList源码对比
- arraylist arraylist使用实例 linkedlist linkedlist源码解析 linkedlist和arraylist的区别
- ArrayList和LinkedList的源码分析
- 【JDK】:ArrayList和LinkedList源码解析
- ArrayList和LinkedList add的源码分析
- java ArrayList 和 LinkedList 源码解析比较
- ArrayList和LinkedList源码分析总结
- JDK源码解析之ArrayList和LinkedList
- JAVA拾遗 - ArrayList\LinkedList\HashMap源码解析与阅读
- Java集合源码阅读笔记-LinkedList
- UVA - 10384 推门游戏(IDA*+剪枝)
- IPA安装包瘦身指南
- Oops信息及栈回溯
- JVM理论与实践【内存结构】
- Xcode 7 你能不能再抗扎腾点儿呢 - 尤其自个儿强制升级后,没事儿就关闭
- ArrayList和LinkedList源码阅读笔记
- Hadoop动态调整Map Task内存资源大小
- oracle统计字符串中某个字符出现的次数
- 光立方——电子制作的软件模拟
- 载入和显示纹理
- 5-2 UVA 1594 Ducci Sequence (Ducci序列)
- redis 学习手册之redis服务操作命令
- Hadoop关键任务Job资源隔离方案
- 翻译:采用现代Objective-C