首页 > 编程语言 >学习一下Java的ArrayList和contains函数和扩容机制

学习一下Java的ArrayList和contains函数和扩容机制

时间:2023-10-25 19:56:44浏览次数:36  
标签:index contains Java 容量 int ArrayList elementData minCapacity

起因

在Leetcode上做题写了两种暴力解法,但是执行效率上不太一样。
image

时间上差很远,内存虽然差不多但是前者击败30%,后者击败94%。这两种解法区别是用一条ArrayList还是两条来存数据,所以contains虽然执行次数一样但是检测的长度上不一样,而且ArrayList的扩容次数也不一样,所以学习一下。

contains(Object o)

直接翻(JDK8)源码:
image
nullobject区分开来还是因为equals有一方是null的话都会导致异常. 合并一起写的话可以用Objects.equals(obj1, obj2)的写法.
所以显然暴力解法用到的contains原理就是朴实无华的一遍遍搜索所以时间特别长.

ArrayList扩容机制

省流: 直接看最下面的grow函数.

如果是默认的ArrayList, 添加元素时会先计算数组长度, 如果元素个数+1大于当前数组长度+1大于elementData.length时进行扩容,扩容后的数组大小是: oldCapacity + (oldCapacity >> 1) 可以理解成1.5倍扩容。

涉及到的源码:

// 向指定索引位置插入元素
public void add(int index, E element) {
    // 检查索引范围
    rangeCheckForAdd(index);

    // 确保容量足够
    ensureCapacityInternal(size + 1);  // 增加 modCount(用于支持并发修改的计数器)
    // 使用 System.arraycopy 将元素后移,为新元素腾出位置, 这是跟另一个add的区别⭐⭐⭐⭐⭐
    System.arraycopy(elementData, index, elementData, index + 1, size - index);
    elementData[index] = element; // 在指定位置插入新元素
    size++; // 更新列表大小
}

// 在列表末尾添加元素
public boolean add(E e) {
    // 确保容量足够
    ensureCapacityInternal(size + 1);  // 增加 modCount
    elementData[size++] = e; // 在列表末尾添加新元素
    return true;
}

// 内部方法:确保容量足够
private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

// 内部方法:计算容量
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        // 如果内部数组为空,返回默认容量或所需容量中的较大者
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity; // 否则返回所需容量
}

// 内部方法:确保容量足够
private void ensureExplicitCapacity(int minCapacity) {
    modCount++; // 增加并发修改计数器

    // 检查容量是否足够,如果不够则扩展
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

// 内部方法:扩展容量
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); // 处理可能的巨大容量情况
    // 使用 Arrays.copyOf 扩展数组容量
    elementData = Arrays.copyOf(elementData, newCapacity);
}


实际上Array.copyof底层调用的还是System.arraycopy.

标签:index,contains,Java,容量,int,ArrayList,elementData,minCapacity
From: https://www.cnblogs.com/joey-redfield/p/17787980.html

相关文章

  • java笔记——面向对象
    1.概述:面向对象是基于面向过程的编程思想举例:把大象装进冰箱2.开发:不断的创建对象,使用对象,指挥对象做事情3.面向对象特征:封装,继承,多态4.类和对象的关系:类是一组相关的属性和行为的集合对象是该类事物的具体体现5.用class描述事物:成员变量就是事物的属性,成员方法就......
  • Java笔记——数组静态初始化开始
    一维数组:静态初始化:定义格式:(1)数据类型[]数组名=new数组类型[](2)数组类型[]数组名={元素1,元素2,.....}练习:数组元素逆序:publicstaticvoidmain(String[]args){int[]arr={1,2,3,4,5,6,7,8,9,10};System.out.println("逆序前:");for(inti......
  • 超市自助付款系统 JAVA开源项目 毕业设计
    https://gf.bilibili.com/item/detail/1103977029为了帮助小白入门Java,博主录制了本项目配套的《项目手把手启动教程》,希望能给同学们带来帮助。一、摘要本博客设计实现了超市购物自助付款系统,该系统采用最新的技术,包括Vue以及SpringBoot等技术方法,实现了快速精准的商品结算,同时,......
  • 校园二手交易系统 JAVA开源项目 毕业设计
    https://gf.bilibili.com/item/detail/1103978029为了帮助小白入门Java,博主录制了本项目配套的《项目手把手启动教程》,希望能给同学们带来帮助。一、摘要随着国家生产力的发展,越来越多商品被生产了出来,超过了人们的实际消耗量,所以产生了大量闲置的商品,这些闲置商品有些被遗弃、有......
  • 智能停车场管理系统 JAVA开源项目 毕业设计
    https://gf.bilibili.com/item/detail/1103632029为了帮助小白入门Java,博主录制了本项目配套的《项目手把手启动教程》,希望能给同学们带来帮助。一、摘要随着我国经济的不断发展,人民生活水平的也日益提高,外出购物、旅游意向也越来越强,对交通出行的需求也越来越大。在一些大型商贸......
  • 【百度智慧云】语音技术-短语音识别 JavaScript
    提要代码目的:通过JavaScript代码,完成用百度智能云的语音技术-短语音识别功能,实现语音转文字效果。需要先有百度智慧云账户,且开通短语音试别业务以下是使用到的数据信息:AccessToken获取方式cuid获取方式测试音频点击下载-JianWangChao.wav点击下载-jiarenmen.wav......
  • Java系列 | 如何讲自己的JAR包上传至阿里云maven私有仓库【云效制品仓库】
    什么是云效云效是云原生时代一站式BizDevOps平台,产研数字化同行者,支持公共云、专有云和混合云多种部署形态,通过云原生新技术和研发新模式,助力创新创业和数字化转型企业快速实现产研数字化,打造“双敏”组织,实现10倍效能提升。制品仓库Packages云效制品库Packages致力于帮助开......
  • Java 中带标签的 break 和 continue
    看视频无意中学到的一个小知识点,偶尔会有用到的地方,是很方便的一个技巧。在循环外面加:自定义的标签名+冒号,在循环内用 break或者continue时后面接这个标签名就可以跳出指定的循环了。以下是三个示例代码:classHelloJava{publicstaticvoidmain(String[]args){......
  • Java 求两个数的最大公约数和最小公倍数(理解原理 > 背诵)
    解题需知原理,背诵来的知识只能支撑一时。为什么反复执行a%b,即可得到最大公约数?(设定前提是a>b)其中的数学原理就是:a和b的最大公约数完全等同于 b和a%b的最大公约数,证明在这里:辗转相除法求解最大公约数和最小公倍数的数学原理-知乎求得最大公约数d以后,比方说:a=x*......
  • Java基础20问(1-5)
    1.Java面向对象和面试过程的区别?面向过程是将一个问题拆解成几个步骤,依次实现每一个步骤,比如实现一个冒泡排序的算法,是为了解决某个非常具体的问题。而面向对象也是将一个问题拆解成几个步骤,但是先不去实现,而是根据这些步骤抽象出若干个类,每个类都有属性和方法,咱配合着把问题解决。......