ArrayList的深入理解

news2024/11/19 20:23:37

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.coloradmin.cn/o/418899.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pandas 2.0 vs Polars:速度的全面对比

前几天的文章&#xff0c;我们已经简单的介绍过Pandas 和Polars的速度对比。刚刚发布的Pandas 2.0速度得到了显著的提升。但是本次测试发现NumPy数组上的一些基本操作仍然更快。并且Polars 0.17.0&#xff0c;也在上周发布&#xff0c;并且也提到了性能的改善&#xff0c;所以我…

Apple苹果开发者Certificates, Identifiers Profiles创建

1.创建Profile: 登陆Apple开发者账号,进入开发者后台,选择Profiles 然后点击Generate a Profile生成一个配置 选择配置类型 点击继续 选择APP ID 创建APP ID 注册一个新的APP id 选择应用类型,然后点击继续

两种事件处理模式:reactor/proactor

&#xff01;&#xff01;同步通常是reactor&#xff0c;异步通常是proactor reactor 要求主线程&#xff08;I/O处理单元&#xff09;只负责监听文件描述符上是否有事件发生&#xff0c;有的话就立即将该事件通知工作线程&#xff08;逻辑单元&#xff09;&#xff0c;将 so…

SpringBoot——单元测试实践总结

文章目录单元测试概念作用黑白盒黑盒测试白盒测试逻辑覆盖1、语句覆盖2、判定覆盖3、条件覆盖4、条件/判定覆盖5、条件组合覆盖6、路径覆盖SpringBoot工程单测介绍pom依赖注意&#xff1a;Idea结构创建路径创建类和方法Controller层单测被测代码测试代码Service层单测被测代码测…

springboot集成hadoop3.2.4HDFS

前言 记录springboot集成hadoop3.2.4版本&#xff0c;并且调用HDFS的相关接口&#xff0c;这里就不展示springboot工程的建立了&#xff0c;这个你们自己去建工程很多教程。 一、springboot配置文件修改 1.1 pom文件修改 <!-- hadoop依赖 --><dependency><gro…

【从零开始学Skynet】基础篇(八):简易留言板

这一篇我们要把网络编程和数据库操作结合起来&#xff0c;实现一个简单的留言板功能。 1、功能需求 如下图所示&#xff0c;客户端发送“set XXX”命令时&#xff0c;程序会把留 言“XXX”存入数据库&#xff0c;发送“get”命令时&#xff0c;程序会把整个留言板返回给客户端。…

怎么把视频转成mp3音频,下面有四个方法

你有没有遇到过这种情况&#xff0c;看了一部电影或者纪录片&#xff0c;里面的背景音乐或者对白让你很感动&#xff0c;但是我们只需要其中的音频部分&#xff0c;比如在手机上收听音乐或者创作自己的音频内容。这时候我们可以先把视频保存下来&#xff0c;然后通过视频转音频…

光耦继电器工作原理及优点概述

光耦继电器是一种电子元器件&#xff0c;也是固态继电器的一种&#xff0c;其主要作用是隔离输入与输出电路&#xff0c;用于保护或者控制电路的正常工作。 光耦继电器工作原理是利用光电转换器将外界信号转化为光信号&#xff0c;通过光纤传输到另一端&#xff0c;再由另一端的…

【C生万物】 数组篇

欢迎来到 Claffic 的博客 &#x1f49e;&#x1f49e;&#x1f49e; 前言&#xff1a; 这个专栏好久没更新了&#xff0c;今日诗兴大发&#xff0c;打算尽快完成这个专栏&#xff0c;这期讲数组。 目录 Part1:一维数组 1.创建 2.初始化 3.使用 4.在内存中的存储 Part2:二…

安卓开发学习记录(续)

文章目录十一、综合训练&#xff08;购物车功能&#xff09;十二、内容提供者Provider十一、综合训练&#xff08;购物车功能&#xff09; 实现功能&#xff1a; 手机商品页面展示&#xff0c;加入购物车功能&#xff0c;商品详情页面&#xff0c;清空购物车&#xff0c;删除购…

C++算法初级9——递归

C算法初级9——递归 文章目录C算法初级9——递归递归求阶乘递归求斐波那契数列递归&#xff0c;简单地来说&#xff0c;就是一个函数自己调用自己。函数f()就好像是工厂中生产零件的模板&#xff0c;每次我们调用函数f()的时候&#xff0c;都会依照模板生产一个新的零件&#x…

项目4:后台管理的开发和使用(前端)

项目4&#xff1a;后台管理的开发和使用&#xff08;前端&#xff09; 1.npm包管理器的基本学习 2.利用现成后台管理系统开发 3.后台管理系统的路由配置 4.后台管理系统的地址访问配置 5.前后端联调 6.完善积分等级的前端系统 7.对前端系统的全面分析&#xff08;Vue组件…

跳槽进阿里了,其实也没那么难...

对于很多没有学历优势的人来说&#xff0c;面试大厂是非常困难的&#xff0c;这对我而言&#xff0c;也是一样&#xff0c;出身于二本&#xff0c;原本以为就三点一线的生活度过一生&#xff0c;直到生活上的变故&#xff0c;才让我有了新的想法和目标&#xff0c;因此我这个二…

【C++ -模块一 常量变量、关键字、数据类型】

C 模块一C框架代码&#xff1a;第一个C程序&#xff0c;打印hello C &#xff01;代码注释&#xff1a;一 变量和常量&#xff1a;1.1变量变量创建语法&#xff1a;1.2 常量&#xff1a;不能被修改的数据&#xff08;1&#xff09; #define定义的宏常量&#xff1a;一般写在文件…

排序(3)之交换排序

目录 前言 交换排序 1.冒泡排序 1.1冒泡排序的实现 1.2 特性总结 2.快速排序 2.1hoare版本 2.2 挖坑法 2.3 前后指针版本 3.快速排序的优化 3.1 三数取中法 3.2 小区间优化 4.快速排序的非递归实现 前言 今天小编给大家带来交换排序的内容&#xff0c;对于交换排序…

C-关键字(下)

文章目录循环控制switch-case-break-defaultdo-while-forgetchar()break-continuegotovoidvoid*returnconstconst修饰变量const修饰数组const修饰指针指针补充const 修饰返回值volatilestruct柔型数组union联合体联合体空间开辟问题利用联合体的性质,判断机器是大端还是小端enu…

力扣javascript刷题343——动态规划之整数拆分

这几天有在开始投暑期实习的简历&#xff0c;可能确实是投的太晚了&#xff0c;好多厂都没有hc了&#xff0c;阿里简历面都没过&#xff08;感觉是kpi面试&#xff09;&#xff0c;被深深打击到了呜呜呜&#xff0c;花了两天整理情绪&#xff0c;重新出发&#xff0c;下篇文章针…

mysql 索引详解

mysql 索引索引分类1. 普通索引和唯一索引2. 单列索引和组合索引3. 全文索引4&#xff0e;空间索引操作使用索引1. 在已有表中添加索引2. 删除索引索引是一个单独存储在磁盘上的数据库结构&#xff0c;使用索引可以快速找出在某个或多个列中有一特定值的行&#xff0c;提高查询…

【C语言 -结构体 结构体声明、定义、初始化、结构体成员访问、结构体传参】

C语言 - 结构体声明、定义、初始化、结构体成员访问、结构体传参一 结构体类型的声明&#xff1a;声明格式&#xff1a;二 结构体的定义并初始化2.1用结构体创建&#xff08;定义&#xff09;结构体变量&#xff08;对象&#xff09;的两种方式&#xff1a;&#xff08;1&#…

WebRTC 系列(三、点对点通话,H5、Android、iOS)

WebRTC 系列&#xff08;二、本地 demo&#xff0c;H5、Android、iOS&#xff09; 上一篇博客中&#xff0c;我已经展示了各端的本地 demo&#xff0c;大家应该知道 WebRTC 怎么用了。在本地 demo 中是用了一个 RemotePeerConnection 来模拟远端&#xff0c;可能理解起来还有点…