Java List源码研究
来源:互联网 发布:荧光颜料淘宝 编辑:程序博客网 时间:2024/06/07 11:50
List源码研究
一、概述
ArrayList:【数组实现的】方法不同步、线程不安全、性能相对高,查找速度快,默认扩充为原来的1.5倍。
Vector:【数组实现的】方法同步(sychronized)、线程安全、性能相对低、查找速度快,可设置增长因子,一般扩充2倍。
LinkedList:【双向列表实现的】线程不安全、插入效率高。>>只在末端增删元素,用于保持数据插入的顺序。
二、ArrayList
1、继承了AbstractList,实现了RandomAccess, Cloneable, java.io.Serializable接口。
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
2、初始容量为10.
private static final int DEFAULT_CAPACITY = 10;
3、ArrayList扩容机制 :调用ensureCapacity(int minCapacity)函数,传入扩容参数,如果扩容参数大于默认容量,就调用ensureExplicitCapacity,最终进入grow()函数进行扩容。
grow()函数接收一个minCapacity参数,新容量扩为旧容量的1.5倍。如果新容量大于 MAX_ARRAY_SIZE ,调用hugeCapacity,抛出OutOfMemoryError();否则开始执行Arrays.copyOf()函数,该方法内new了一个数组,调用了System.arraycopy()把旧的元素复制到新的数组中。
public void ensureCapacity(int minCapacity) { int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // any size if not default element table ? 0 // larger than default for default empty table. It's already // supposed to be at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } }private void grow(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); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }
4、add方法实现:要add新元素,首先调用ensureCapacityInternal,此时的容量为原size+1,如果没有超过默认容量,就直接在数组最后插入该元素。
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
5、indexOf方法实现:可以看处Array是支持null元素的,首先是判断对象是否为null,然后用for循环进行查找。查找失败的时候返回-1.
public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; }
三、Vector
1、与ArrayList一样, 继承了AbstractList,实现了RandomAccess, Cloneable, java.io.Serializable接口。
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
2、不同点:自己实现了coptInto方法,并且加上了synchronized同步,ArrayList中是直接调用的System.arraycopy,这样就不能保证复制过程中的同步。
public synchronized void copyInto(Object[] anArray) { System.arraycopy(elementData, 0, anArray, 0, elementCount); }
3、扩容机制:把synchronized修饰符放在了最上面,判断是否需要扩容的函数上,而不是grow上。新容量默认是扩充为旧容量的两倍,但是如果在构造函数的时候传入了自定义的扩容参数,新容量就扩为旧容量+自定义增量的和。
public synchronized void ensureCapacity(int minCapacity) { if (minCapacity > 0) { modCount++; ensureCapacityHelper(minCapacity); } }private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }
4、indexOf:同样也是支持null元素的,唯一不同的是加上了synchronized修饰。
public synchronized int indexOf(Object o, int index) { if (o == null) { for (int i = index ; i < elementCount ; i++) if (elementData[i]==null) return i; } else { for (int i = index ; i < elementCount ; i++) if (o.equals(elementData[i])) return i; } return -1; }
5、addAll方法:首先是被synchronized修饰,然后调用toArray()方法先将传入的集合放到一个对象数组中,然后获得数组的长度,判断是否需要扩容,然后再调用System.arraycopy()函数完成复制,最后更新当前的元素总数。
public synchronized boolean addAll(Collection<? extends E> c) { modCount++; Object[] a = c.toArray(); int numNew = a.length; ensureCapacityHelper(elementCount + numNew); System.arraycopy(a, 0, elementData, elementCount, numNew); elementCount += numNew; return numNew != 0; }
四、LinkedList
1、继承了AbstractSequentialList,实现了List,Deque, Cloneable和Serializable接口。 因此LinkedList既可以看成是List(列表),也可以看成是Deque(双端队列)。
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
2、内部实现:使用链表实现,每个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; } }
3、add方法:默认是在尾部添加元素。LinkedList中定义了一个last节点,该节点是记录当前最后一个节点last,然后把新节点赋给last,如果该节点为空,该节点就设为新的头节点first,如果不为空,就把该节点赋给l.next。
public boolean add(E e) { linkLast(e); return true; }void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; }
阅读全文
0 0
- Java List源码研究
- java源码研究-HashMap
- Java源码阅读-List
- java.lang.Boolean源码研究
- 【JAVA】BitSet的源码研究
- Java LinkedList详解源码研究
- 『java.util』 list 接口研究
- java之list源码浅析
- java.util.List源码分析
- java list接口 源码解析
- .NET Framework源码研究系列之---马甲List
- Java学习篇之---研究tomcat源码
- 最近在研究java.util的源码
- java并发包源码阅读笔记(1)-AQS源码研究
- java集合源码解析(三)--List
- Android Gems - Java源码分析之List
- Java集合详解及List源码分析
- java集合源码之List-ArrayList
- super函数没有那么简单-super原理剖析
- Java并发集合框架简介
- 机器学习:线性回归(Linear Regression)小项目
- 2017/8/31 开学四天
- java鬼混笔记:shiro 3、shiro下的散列操作(MD5,SHA-1)
- Java List源码研究
- 归并排序
- Java Set 源码分析
- JAVA Map 源码分析
- 跟我一起写 Makefile(一)
- 详解coredump
- Linux开发学习笔记
- WebSocket实现主动推送交互【编辑中】
- jsp中的EL表达式的用法