深入理解ArrayList
来源:互联网 发布:高科技app软件 编辑:程序博客网 时间:2024/06/05 05:20
说明
本文是基于JDK7对ArrayList进行总结。通过阅读源码,对ArrayList的实现原理,特点等进行理解和掌握。
正文
ArrayList的特点
ArrayList的实现是基于动态数组的,插入数据有序(读取顺序与存放时的顺序一致)且允许重复,允许有空值,但是非线程安全的,适合查找多增删少的场景。
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
ArrayList继承自AbstractList类,实现了List, RandomAccess, Cloneable, java.io.Serializable接口。
ArrayList的成员变量
private transient Object[] elementData;//从这里可以看出,底层是一个数组 private int size;//ArrayList的大小,即所含元素的个数 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//允许数组的最大size
ArrayList的构造函数
ArrayList一共有三个构造函数
指定容量的构造函数
public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; }
缺省构造函数
public ArrayList() { this(10);//ArrayList默认大小为10 }
指定一个集合作为参数的构造函数
public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); size = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); }
ArrayList的add(E e)方法
我们知道了ArrayList的底层是一个数组,当向其添加数据时,如果数组已满,它是怎样确保数据可以正常的添加?
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
我们可以看到进入方法时,首先调用了ensureCapacityInternal(size + 1)方法,后面注释可以看到,它是增加modCount的值
ensureCapacityInternal(int minCapacity)方法
private void ensureCapacityInternal(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
通过本方法我们可以看到,当调用add方法时,modCount值加1,modCount值记录的时ArrayList结构改变的次数。若添加后的元素个数超过数组的长度,就会调用grow(minCapacity)方法
grow(int minCapacity)方法
private void grow(int minCapacity) { // overflow-conscious code 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); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity);//以新大小复制原数组的拷贝,并改原数组 }
通过本方法我们就可以知道上述问题的解决办法,ArrayList有自动扩容机制,当底层数组容量满时,容量就会自动扩大为原来的1.5倍
ArrayList的get(int index)方法
public E get(int index) { rangeCheck(index); return elementData(index); }
当以索引查找数据时,先判断索引是否越界,是,抛出IndexOutOfBoundsException异常;否,则直接返回索引对应位置的值
rangeCheck(int index)方法
private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
ArrayList的remove(int index)方法
remove方法删除数组的元素后,其之后的元素会发生移动,性能开销较大,
public E remove(int index) { rangeCheck(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; // Let gc do its work return oldValue; }
从本方法可以看出,数组元素的移动是通过复制完成的,从数组的index+1开始复制到原数组从index开始,将原来index之后的元素全部向前移一位。删除后,将数组最后一位置为null,让垃圾回收器进行回收
我们注意到除了remove(int index)方法,还有一个fastRemove(int index),与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; // Let gc do its work //没有返回值 }
那这个方法什么时候使用? 通常在以元素自身为参数,删除数组中的此元素时使用
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++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; }
ArrayList的迭代
ArrayList有两种迭代器 Iterator 和 ListIterator
Iterator可以用于所有集合,Set,List和Map和这些集合的子类型,而ListIterator只能用于List及其子类型。
两种迭代器的区别,详见http://blog.csdn.net/longshengguoji/article/details/41551491
- 深入理解ArrayList
- 深入理解ArrayList
- 深入理解ArrayList
- ArrayList深入理解
- 深入理解ArrayList
- 深入理解ArrayList
- 深入理解ArrayList
- ArrayList的深入理解(学习)
- 深入理解ArrayList与LinkedList的区别
- Java 集合深入理解(7):ArrayList
- 深入理解ArrayList与LinkedList的区别
- Java进阶--深入理解ArrayList实现原理
- Java 集合深入理解(7):ArrayList
- Java 集合深入理解(7):ArrayList
- Java 集合深入理解(7):ArrayList
- 深入理解ArrayList 和 LinkedList 区别
- 深入理解容器系列片之二--------ArrayList的总结
- 深入理解容器系列之二--------ArrayList的总结
- Excel 处理单元格中文字间空格问题。
- 《笨办法学python》加分习题6——我的答案
- MySQL锁详解
- IOS块与多线程
- STM8S汇编入门(1-3)
- 深入理解ArrayList
- 从0开始搭建阿里云(腾讯云)ubuntu16.04 nodejs + nginx + mysql + pm2 服务(三、搭建mysql环境)
- Windows常用快捷键
- Rxjava2 源码解析(一)
- php框架是什么?
- [ubuntu] windows 和 ubuntu 火狐浏览器无法同步问题
- STM32定时器的番外(未完)
- Condition源码分析
- Linux实现强实时性的需求与方法