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

相关文章

  • Java超全面梳理内部类的使用

    Java超全面梳理内部类的使用

    说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉。原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法。今天我们就来一探究竟
    2022-04-04
  • 解决rocketmq-client日志保存路径的问题

    解决rocketmq-client日志保存路径的问题

    这篇文章主要介绍了解决rocketmq-client日志保存路径的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • SpringDataRedis入门和序列化方式解决内存占用问题小结

    SpringDataRedis入门和序列化方式解决内存占用问题小结

    spring-data-redis是spring-data模块的一部分,专门用来支持在spring管理项目对redis的操作,这篇文章主要介绍了SpringDataRedis入门和序列化方式解决内存占用问题,需要的朋友可以参考下
    2022-12-12
  • SpringBoot JPA实现查询多值

    SpringBoot JPA实现查询多值

    这篇文章主要为大家详细介绍了SpringBoot JPA实现查询多值,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • java自定义异常以及throw和throws关键字用法

    java自定义异常以及throw和throws关键字用法

    这篇文章主要介绍了java自定义异常以及throw和throws关键字用法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • 基于Spring + Spring MVC + Mybatis 高性能web构建实例详解

    基于Spring + Spring MVC + Mybatis 高性能web构建实例详解

    这篇文章主要介绍了基于Spring + Spring MVC + Mybatis 高性能web构建实例详解,需要的朋友可以参考下
    2017-04-04
  • Java基础之序列化与反序列化详解

    Java基础之序列化与反序列化详解

    这篇文章主要介绍了Java基础之序列化与反序列化详解,文中有非常详细的代码示例,对正在学习java基础的小伙伴们有很好的帮助,需要的朋友可以参考下
    2021-04-04
  • 详解SpringSecurity中的Authentication信息与登录流程

    详解SpringSecurity中的Authentication信息与登录流程

    这篇文章主要介绍了SpringSecurity中的Authentication信息与登录流程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • java 百度手写文字识别接口配置代码

    java 百度手写文字识别接口配置代码

    本文通过实例代码给大家介绍了java 百度手写文字识别接口配置方法,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2022-01-01
  • 两天没解决的问题chatgpt用了5秒搞定隐藏bug

    两天没解决的问题chatgpt用了5秒搞定隐藏bug

    这篇文章主要为大家描述了我用了两天没解决的问题chatgpt用了5秒搞定的全程介绍,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04

最新评论