ArrayList源码解读
来源:互联网 发布:mac磁盘分区 编辑:程序博客网 时间:2024/06/02 21:47
ArrayList源码分析
ArrayList特点总结
- ArrayList实现List接口,底层是使用数组实现的,可以根据元素的个数进行动态扩容
ArrayList线程不安全而Vector是线程安全的,多线程环境下,可以考虑使用
List list = Collections.synchronizedList(new ArrayList(...));
- 元素可以是null
- 查询修改元素的时间复杂度O(1),而插入删除为O(n)
- 构造方法 有3种 一种是指定list的容量 一种是无参构造方法 还有一种是使用一个Collection为参数
- 扩容方法 见grow方法 int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容当前数组长度的一半 1.8之前是 newCapacity = (oldCapacity * 3)/2+1
源码分析
为了代码的简洁,将非核心的代码去掉了,这里还是想说英文的注释是最好的学习材料,有条件的还是应该多看源码中的英文注释
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ //实现List接口 //实现RandomAccess接口,可以进行随机访问 //实现Cloneable接口,可以被clone //实现序列化接口 private static final long serialVersionUID = 8683452581122892189L; //默认的初始容量是10,也就是数组的大小默认是10,面试时会问问 private static final int DEFAULT_CAPACITY = 10; //两个空的数组对应不同的构造方法 private static final Object[] EMPTY_ELEMENTDATA = {}; //默认容量的空数组 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //存储ArrayList元素的数组 //任何一个空的ArrayList(使用elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA进行初始化的, //在第一个元素被add的时候都会自动扩容到DEFAULT_CAPACITY) //使用transient时为了不被序列化 transient Object[] elementData; //ArrayList中元素的个数 private int size; //构造方法 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { //初始化容量 this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { //当初始化容量为0的时候 elementData = {} this.elementData = EMPTY_ELEMENTDATA; } else { //初始化容量<0时 抛出异常 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } //无参构造方法,elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA 当第一个元素被添加的时候扩容到10 //jdk1.7的时候 好像是this(10) public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //构造方法 参数是一个Collection对象 public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); //将c转成数组对象 if ((size = elementData.length) != 0) { // 判断elementData的类型 因为c.toArray不一定返回的Object[] 见 // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6260652 if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // 替换空数组 this.elementData = EMPTY_ELEMENTDATA; } } //将数组中的元素剔除,这样可以使ArrayList实例占用的存储空间尽可能小 public void trimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } } //判断当前ArrayList的容量是否够用 public void ensureCapacity(int minCapacity) { int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) ? 0 : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //minCapacity为默认大小10和参数指定大小的较大值 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; if (minCapacity - elementData.length > 0) //如果参数minCapacity比数组长度长就进行扩容 grow(minCapacity); } //用来扩容的函数 private void grow(int minCapacity) { int oldCapacity = elementData.length; //获取当前数组长度 int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容当前数组长度的一半 1.8之前是 newCapacity = (oldCapacity * 3)/2+1 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //如果新容量还是比指定的minCapacity小就将容量扩充到minCapacity if (newCapacity - MAX_ARRAY_SIZE > 0) //新容量超过了Integer.MAX_VALUE - 8 可能是Integer.MAX_VALUE newCapacity = hugeCapacity(minCapacity); // minCapacity通常是接近size的 elementData = Arrays.copyOf(elementData, newCapacity); } //返回的是一个合理的容量值 private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; //Integer.MAX_VALUE - 8 } //获取ArrayList中元素的个数 public int size() { return size; } //判断是够为空 public boolean isEmpty() { return size == 0; } //判断是否含有某个元素注意这种情况(o==null?e==null:o.equals(e)) //因为ArrayList可以塞进null,所以当o是null的时候只要ArrayList中元素e也是null就返回true //如果o不是null的话,就是使用equals判断list中是否含有元素o public boolean contains(Object o) { return indexOf(o) >= 0; } //返回list中元素的下标(第一个),如果存在就返回该元素下标,如果不存在就返回-1 public int indexOf(Object o) { if (o == null) { //如果元素指定的元素是null for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { //指定的元素不为null for (int i = 0; i < size; i++) if (o.equals(elementData[i])) //循环遍历list 使用eqauls判断list中与指定元素相同的元素 return i; } return -1; } //获取最后一个元素o在list中的下标 public int lastIndexOf(Object o) { if (o == null) { //从后往前找 for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) //使用equals方法判断相同 if (o.equals(elementData[i])) return i; } //如果元素不存在返回-1 return -1; } //clone方法 public Object clone() { try { ArrayList<?> v = (ArrayList<?>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(e); } } //返回数组 public Object[] toArray() { return Arrays.copyOf(elementData, size); } //返回指定index的元素 public E get(int index) { rangeCheck(index); //index合法性检查 return elementData(index); } //根据index对list元素进行赋值 public E set(int index, E element) { rangeCheck(index); //index越界检查 E oldValue = elementData(index); //返回旧值 elementData[index] = element; //设置新值 return oldValue; } //添加指定的元素到list的末尾 public boolean add(E e) { ensureCapacityInternal(size + 1); // 确保添加一个元素不会越界 如果是DEFAULTCAPACITY_EMPTY_ELEMENTDATA第一次添加的时候list会扩容到默认的10 elementData[size++] = e; return true; } //在指定index添加元素 public void add(int index, E element) { rangeCheckForAdd(index); //index越界检测 ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } //删除指定index的元素并返回原先的元素 public E remove(int index) { rangeCheck(index); //index下标检查 modCount++; E oldValue = elementData(index); //获取原先的值 int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // GC //返回原先的值 return oldValue; } //删除list中出现的第一个元素o public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) //遍历使用equals判断相等 if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } //私有的删除方法,在remove中调用,在这个方法中不包含越界检查和返回原来值 private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; //GC } //清空列表 public void clear() { modCount++; for (int i = 0; i < size; i++) elementData[i] = null; //GC size = 0; } //添加Collection中所有的元素到当前的list中 public boolean addAll(Collection<? extends E> c) { //collection转数组 Object[] a = c.toArray(); //获取数组的长度 即元素的个数 int numNew = a.length; //确保list内部数组容量 ensureCapacityInternal(size + numNew); // Increments modCount //复制数组 System.arraycopy(a, 0, elementData, size, numNew); //修改list 元素个数 size += numNew; return numNew != 0; } //指定index向list插入Collection的所有元素 public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); //检查index Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount int numMoved = size - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; } protected void removeRange(int fromIndex, int toIndex) { modCount++; int numMoved = size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // clear to let GC do its work int newSize = size - (toIndex-fromIndex); for (int i = newSize; i < size; i++) { elementData[i] = null; } size = newSize; } //index越界检查,如果不合法抛出一个运行时异常, private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } // add和addAll的越界检查 private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } //下标越界异常信息 private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+size; } //删除Collection中所有的元素 public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, false); } public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, true); } private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { // clear to let GC do its work for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } return modified; }}
阅读全文
0 0
- Java--ArrayList源码解读
- ArrayList源码解读
- Java源码解读-ArrayList
- ArrayList源码解读
- ArrayList源码解读
- ArrayList源码解读
- ArrayList源码解读
- ArrayList详解,源码解读
- ArrayList源码简略解读
- ArrayList扩容源码解读
- ArrayList源码解读
- ArrayList JDK9源码解读
- ArrayList源码解读
- JDK之ArrayList源码解读
- ArrayList底层实现源码解读
- 1.7版本 Arraylist源码解读
- jdk 1.8 arraylist源码解读
- Java 2源码解读:java.util.ArrayList
- 把书读薄:大型网站技术架构-核心原理与案例分析(第三篇 案例)
- Scala容器库(Scala’s Collections Library)
- 总结几种常见web攻击手段及其防御方式
- html5存储
- 前缀表达式转后缀表达式的链栈实现
- ArrayList源码解读
- php按层数获取无限极分类
- R语言-中文乱码解决方法
- 调用摄像头和相册完全解析
- QML 组件属性
- android html唤醒APP(原生)
- Python(1)——Python基础学习框架
- 使用p-namesapce和c-namespace简化bean的定义
- android如何获取listview中的任意行数据