Java的List集合框架之ArrayList详解

 更新时间:2023年11月16日 09:59:20   作者:进击的猫  
这篇文章主要介绍了Java的List集合框架之ArrayList详解,ArrayList默认容量为10(构造方法未指定初始容量为0),扩容是利用位运算(右移一位)和直接相加进行1.5倍扩容,需要的朋友可以参考下

(一)List子父层级

ArrayList继承实现关系

  • List接口继承于Collection,Collection继承Iterable;
  • LIst接口实现类分为:Vector、ArrayList、LinkedLIst;

(二)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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot如何动态创建Bean示例代码

    Spring Boot如何动态创建Bean示例代码

    这篇文章主要给大家介绍了关于Spring Boot如何动态创建Bean的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-09-09
  • springboot使用定时器@Scheduled不管用的解决

    springboot使用定时器@Scheduled不管用的解决

    这篇文章主要介绍了springboot使用定时器@Scheduled不管用的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • SpringBoot实现redis延迟队列的示例代码

    SpringBoot实现redis延迟队列的示例代码

    延时队列场景在我们日常业务开发中经常遇到,它是一种特殊类型的消息队列,本文就来介绍一下SpringBoot实现redis延迟队列的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • java中string.trim()函数的作用实例及源码

    java中string.trim()函数的作用实例及源码

    这篇文章主要介绍了java中string.trim()函数的作用实例及源码,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • 一篇文章带你理解Java Spring三级缓存和循环依赖

    一篇文章带你理解Java Spring三级缓存和循环依赖

    这篇文章主要介绍了浅谈Spring 解决循环依赖必须要三级缓存吗,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-09-09
  • springboot处理url中带斜杠/\字符的参数报400问题

    springboot处理url中带斜杠/\字符的参数报400问题

    这篇文章主要介绍了springboot处理url中带斜杠/\字符的参数报400问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • java中注解的实现原理详解

    java中注解的实现原理详解

    这篇文章主要介绍了java中注解的实现原理详解,注解也叫元数据,例如我们常见的@Override和@Deprecated,注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包、类、接口、字段、方法参数、局部变量等进行注解,需要的朋友可以参考下
    2023-10-10
  • Java实现顺时针输出螺旋二维数组的方法示例

    Java实现顺时针输出螺旋二维数组的方法示例

    这篇文章主要介绍了利用Java如何实现顺时针输出螺旋二维数组的方法示例,文中给出了详细的示例代码和注释,相信对大家具有一定的参考价值,有需要的朋友们下面来一起看看吧。
    2017-02-02
  • Springboot整合freemarker 404问题解决方案

    Springboot整合freemarker 404问题解决方案

    这篇文章主要介绍了Springboot整合freemarker 404问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • JAVA中DIFF算法实现

    JAVA中DIFF算法实现

    本文主要介绍了JAVA中DIFF算法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07

最新评论