java8源码分析ArrayList
来源:互联网 发布:红薯夫妇知乎扒皮 编辑:程序博客网 时间:2024/05/29 07:18
ArrayList类的声明
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
字段
//默认创建的容量大小private static final int DEFAULT_CAPACITY = 10;//空数组private static final Object[] EMPTY_ELEMENTDATA = {};//默认的空数组常量private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//存放元素的数组transient Object[] elementData;//数组总的元素个数private int size;//数组的最大上限private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
主要方法介绍
构造函数
//无参的构造方法 public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }//定义了初始容量的构造方法 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } //将提供的集合转成数组返回给elementData(返回若不是Object[]将调用Arrays.copyOf方法将其转为Object[]) public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }
通过不同的参数,采用不同的构造方法来创建ArrayList。
add方法
//直接插入对象 public boolean add(E e) { //保证有足够的空间来插入对象 ensureCapacityInternal(size + 1); // Increments modCount!! //插入对象 elementData[size++] = e; return true; } public void add(int index, E element) { //看传入的index值是否小于0或者超过size rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! //把elementData的index后的对象插入到index+1后,即从index开始的对象向后移一位 System.arraycopy(elementData, index, elementData, index + 1, size - index); //要插入的对象插入index位 elementData[index] = element; //将size+1 size++; } private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } private void ensureCapacityInternal(int minCapacity) { //当ArrayList为空对象时 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { //增加一次修改次数 modCount++; // overflow-conscious code //当需要的最小容量大于表单大小的时候 if (minCapacity - elementData.length > 0) //扩容 grow(minCapacity); } private void grow(int minCapacity) { // overflow-conscious code //表单的长度 int oldCapacity = elementData.length; //新的表单长度为老表单的1.5倍 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); }//看所需的最小容量是否比最大容量大,若比最大容量大则返回整型的最大值0x7fffffff,不然就返回0x7FFFFFF7 private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
get方法
//通过下标来获取对象 public E get(int index) { rangeCheck(index); return elementData(index); } //检查获取的值是否超过了ArrayList的大小 private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } //获取对象 E elementData(int index) { return (E) elementData[index]; }
Set方法,比较简单就不解释了
public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; } private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
//通过下标删除 public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); //从index到后的元素个数 int numMoved = size - index - 1; if (numMoved > 0) //将index+1后的所以元素前移一位 System.arraycopy(elementData, index+1, elementData, index, numMoved); //size-1然后将最后一位的对象置为空 elementData[--size] = null; // clear to let GC do its work //返回一移除的元素 return oldValue; }//通过对象删除//分为空和不空的情况,便利元素,然后移除 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; }//和与用下标删除的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; // clear to let GC do its work }
indexOf方法
//通过遍历的方式,找到第一个元素的下标,然后返回下标 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; } //通过反向遍历的方式,找到第一个元素的下标,实际是最后一个,然后返回下标 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--) if (o.equals(elementData[i])) return i; } return -1; }
1.ArrayList不适合频繁插入和删除的场景,因为他每次删除都要通过复制表单的方法来进行,当数据量巨大的时候,这是一笔不小的开支。
2.ArrayList在容量不够用的时候就会进行扩容,每次扩容为1.5倍的前一次的大小。扩容的上限为 Integer.MAX_VALUE。
3.ArrayList是线程不安全的,因为各个方法没有使用synchronized来进行同步。
4.通过下标拿元素,速度快到可以忽略,为O(1).
阅读全文
1 0
- Java8 ArrayList源码分析
- java8源码分析ArrayList
- 【Java8源码分析】集合框架-ArrayList
- java8 ArrayList源码阅读
- Java8 - ArrayList源码
- java8 ArrayList源码阅读
- java8 ArrayList源码阅读
- Java8源码-ArrayList
- ConcurrentHashMap源码分析--Java8
- ConcurrentHashMap源码分析--Java8
- Java8 HashMap源码分析
- Java8 LinkedList源码分析
- Java8 HashMap源码分析
- java8源码分析LinkedList
- java8-HashMap源码分析
- java8 ArrayList源码阅读【2】- 总结
- java8 hashMap介绍 源码分析
- ArrayList源码分析
- 微信小程序地图显示路径问题
- InnoDB存储引擎--1、全文索引
- 无铅工艺中的可焊性分析
- Densely Connected Convolutional Networks-2017 CVPR 优秀论文
- Linux内核 kmalloc, kzalloc & devm_kzalloc 区别
- java8源码分析ArrayList
- java使用Filter实现全栈压缩
- 简单的第三方分享QQ
- jar包和war包的介绍和区别
- acm网站
- mybatis-generator 代码自动生成工具(maven方式)
- 深入理解RunLoop
- 浅谈flex布局
- LIN总线协议记录