当前位置: 首页 > article >正文

ArrayList的深入理解

ArrayList的源码解析

  • 1. 实例化无参构造器
  • 2. add()方法
    • 2.1. add()List的扩容
  • 3. get()方法
  • 4. remove()
  • 5. modCount++ 的作用(面试题)
  • 5. 手写简单List实现存储删除

1. 实例化无参构造器

  • Arraylist作为日常最一个类,内部是动态扩容数组,与普通数组的区别就是它是没有固定大小的限制,并且是线程不安全的
  • 先看实例化的无参构造器
    在这里插入图片描述
  • 执行实例化是要调用其无参构造方法,无参构造方法就是给elementData初始化分配地址值,也就是实例化一下,不初始化的默认值为null
    在这里插入图片描述
 transient Object[] elementData; // non-private to simplify nested class access
 
 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

2. add()方法

在这里插入图片描述

  • 在认识一下源码中的Size,也就是数组的长度大小
  • 源码中的DEFAULT_CAPACITY 也就是数组的默认值的大小
    在这里插入图片描述

在这里插入图片描述

  • size默认的初始化是0,调用的是ensureCapacityInternal()传递的是长度+1的数值
    在这里插入图片描述
    在这里插入图片描述
  • 看一下方法,传递的参数是elementData,也就是list存储元素的数组和minCapacity,也就是长度+1数组的长度
  • 这个判断是判断地址值是否相等,相等的话,在(默认值10,和传递的minCapacity 是数字的默认值+1),现在是返回的是10,因为10大
    在这里插入图片描述
  • modCount++; 这个操作,最后在说
  • minCapacity是刚才调用的calculateCapacity方法返回的默认值和传递的大小中的最大值,目前是10
  • 判断:如果10(默认长度)-elementData.length(默认值0)>0,这个就是ArrayList中核心的一个数组扩容的方法,超过了数组的容量限制执行扩容方法
    在这里插入图片描述
    grow方法
    oldCapacity 是数组原来的长度,现在是0
    newCapacity是数组新的长度,用老数组位移得到
    如果新数组长度-minCapacity(10初始化)=0,新的数组长度就是默认值10初始化默认值10
    最后就是拷贝一份,将原elementData拷贝出来一份默认值为10的数组
    在这里插入图片描述
  • 致此,这个阶段就完成了,第一次add的ensureCapacityInternal方法的作用是初始化了一个长度为10的数组
  • 然后将元素添加到数组之中返回true
    在这里插入图片描述

2.1. add()List的扩容

  • List的扩容机制体现在这里 ,第一次初始化需要扩容数组长度是10
  • 然后以后每次扩容依靠的是,是够超过了数组的容量,然后进行扩容,扩容执行的是grow方法,非扩容直接添加
    在这里插入图片描述
    在这里插入图片描述
  • 扩容扩原数组的1.5倍大小,然后copy一个新的数组,进行返回
    在这里插入图片描述

3. get()方法

  • get方法就是,传递的index超过了数组的长度就抛异常
  • return elementData(index);
    在这里插入图片描述

4. remove()

  • remove方法其实就是一个拷贝的过程
第一个参数默认是src 来源数组 类型为数组
第二个参数默认是srcPos 从来源数组开始复制的位置 类型为整行(其实就是下标)
第三个参数默认是dest 目标数组 类型为数组
第四个参数默认是destPos 目标数组接收起始位置类型为整行(其实就是下标)
第五个参数默认是length 复制的长度

在这里插入图片描述

5. modCount++ 的作用(面试题)

  • 通过看源码发现add和删除等一些地方有modCount++这个代码,这个代码的作用是,在遍历中,为了避免一边修改数据,一边拿数据,进而造成的数据混乱
 public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();
 
            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

5. 手写简单List实现存储删除

package com.rj.bd.Test;

import lombok.Data;

import java.util.Arrays;

/**
 * @author LXY
 * @desc
 * @time 2023--04--10--10:46
 */
public class YList<T> {
    //初始化
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    //数组初始化默认大小
    private  static  final  int DEFAULT_CAPACITY =10;

    Object[] elementData;
    //初始化0
    private  int Size;

    //添加方法
    public  void add(T e){
        ensureCapacityInternal(Size+1);
        elementData[Size++]=e;
    }


    public void  remove(int index) {
        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
    }



    //添加方法
    public  T get(int index){
        if (elementData.length-index<0){
            try {
                throw  new Exception("数组越界");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return (T) elementData[index];
    }


    //判断最大值
    private int ensureCapacityMax(int minsize){
        return Math.max(minsize, Size);
    }

    private void ensureCapacityInternal(int minsize) {
        int indexs = ensureCapacityMax(minsize);

        if (indexs>elementData.length){
            grep(indexs);
        }
    }

    //扩容方法
    private void grep(int minCapacity) {
        //原来的长度
        int oldCapacity=elementData.length;
        int newCapacity= oldCapacity + (oldCapacity >> 1);

        if (newCapacity-minCapacity<0){
            newCapacity=DEFAULT_CAPACITY;
        }
        elementData = Arrays.copyOf(elementData, newCapacity);
    }


    //无参构造器,初始化
    public  YList (){
        elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }



}


http://www.kler.cn/a/10504.html

相关文章:

  • Qt初识简单使用Qt
  • Flink API 的层次结构
  • Android Profiler 内存分析
  • GFPS技术原理(四)GATT特征值
  • SpringBoot整合Freemarker(三)
  • Kafka 快速入门(一)
  • 不会注册ChatGPT?4个国内网站让你尽情体验
  • GameFramework 框架详解之 如何接入热更框架HybridCLR
  • 【音频处理】创建环绕声混响
  • pycharm笔记
  • 内部人员或给企业造成毁灭性损失
  • LAZADA将缩短履约时效,卖家发货倍感压力
  • 代码随想录_226翻转二叉树、101对称二叉树
  • item_search_img-按图搜索1688商品(拍立淘)接口的接入参数说明
  • 跟着AI学AI(2): 逻辑回归
  • Spring Cloud快速入门
  • 网络安全之入侵检测
  • NVIDIA- cuSPARSE(四)
  • 【Flutter进阶】聊一聊组件中的生命周期、状态管理及局部重绘
  • 数据优化 | CnOpenDataA股上市公司招聘数据
  • 关于合金电阻
  • vue项目用后端返回的文件流实现docx和pdf文件预览
  • Java 进阶(11) 线程安全
  • virtualbox如何配网
  • 含有分布式电源的三相不平衡配电网潮流计算【IEEE33节点】(Matlab代码实现)
  • 还不懂如何与AI高效交流?保姆级且全面的chatGPT提示词工程教程来啦!(一)基础篇