java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > List集合框架之ArrayList

Java的List集合框架之ArrayList详解

作者:进击的猫

这篇文章主要介绍了Java的List集合框架之ArrayList详解,ArrayList默认容量为10(构造方法未指定初始容量为0),扩容是利用位运算(右移一位)和直接相加进行1.5倍扩容,需要的朋友可以参考下

(一)List子父层级

ArrayList继承实现关系

(二)List实现类

1、ArrayList实现类

(1)ArrayList底层是Object数组,transient Object[] elementData;

(2)ArrayList默认容量为10或者构造方法指定初始容量,private static final int DEFAULT_CAPACITY = 10;

(3)ArrayList扩容是基于当前容量的1.5倍,int newCapacity = oldCapacity + (oldCapacity >> 1);

(4)ArrayList是线程不安全的,在多线程环境下,会报并发修改异常java.util.ConcurrentModificationException。

2、常见源码

(1)构造方法:

  //无参构造方法,未指定初始容量
  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);
      }
  }

(2)add方法:

  //此处列举常用add(返回值为boolean),其它指定位置插入add(返回空)方法暂不列举,逻辑基本类似
 public boolean add(E e) {
     ensureCapacityInternal(size + 1);//判断是否需要扩容
     elementData[size++] = e;//将值存储在数组上
     return true;
 }
 //判断是否需要扩容,如需要则进行1.5倍扩容
 private void ensureCapacityInternal(int minCapacity) {
     ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
 }
 //判定并计算容量大小值(旧的size+新的1)
 private static int calculateCapacity(Object[] elementData, int minCapacity) {
      if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//判断是否已被初始化
          return Math.max(DEFAULT_CAPACITY, minCapacity);
      }
      return minCapacity;//返回实际已存值大小(size)+将要存储值大小(1)
  }
 //扩容判定
 private void ensureExplicitCapacity(int minCapacity) {
     modCount++;//操作次数
     if (minCapacity - elementData.length > 0)//判定当前数组是否还能存入值
         grow(minCapacity);//扩容
 }
 //数组最大值
 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

 private void grow(int minCapacity) {
     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);//扩容值超大设置
     elementData = Arrays.copyOf(elementData, newCapacity);//数组数据迁移复制
 }
 //判定扩容后的容量是否是超大值
 private static int hugeCapacity(int minCapacity) {
     if (minCapacity < 0) //越界值判定
         throw new OutOfMemoryError();
     //返回扩大值,既可能是Integer最大值也可能是数组最大值
     return (minCapacity > MAX_ARRAY_SIZE)?Integer.MAX_VALUE:MAX_ARRAY_SIZE;
 }

(3)get方法:

 public E get(int index) {
  rangeCheck(index);//越界检查
     return elementData(index);
 }
 //越界检查方法
 private void rangeCheck(int index) {
     if (index >= size)//越界检查
         throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
 }
 //获取索引数据
 E elementData(int index) {
     return (E) elementData[index];//直接将对应索引数据返回
 }

(4)set方法:

 public E set(int index, E element) {
   rangeCheck(index);//检查是否越界,不列举,上述(3)中已列举
     E oldValue = elementData(index);//获取指定索引已存在的值
     elementData[index] = element;//将新值设置到指定索引位置
     return oldValue;//返回旧值
 }

(5)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; //将因删除而导致的空位置空,便于GC
      return oldValue;//将删除的值返回
  }

3、总结

 (1)ArrayList线程不安全,并发操作ArraylList会报并发修改异常java.util.ConcurrentModificationException。

 (2)ArrayList默认容量为10(构造方法未指定初始容量为0),扩容是利用位运算(右移一位)和直接相加进行1.5倍扩容。

到此这篇关于Java的List集合框架之ArrayList详解的文章就介绍到这了,更多相关List集合框架之ArrayList内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文