起因

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

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

contains(Object o)

直接翻(JDK8)源码:



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.

学习一下Java的ArrayList和contains函数和扩容机制的更多相关文章

  1. 浅谈JAVA中HashMap、ArrayList、StringBuilder等的扩容机制

    JAVA中的部分需要扩容的内容总结如下:第一部分: HashMap<String, String> hmap=new HashMap<>(); HashSet<Strin ...

  2. [java学习笔记]java语言基础概述之函数的定义和使用&函数传值问题

    1.函数 1.什么是函数? 定义在类中的具有特定功能的一段独立小程序. 函数也叫做方法 2.函数的格式 修饰符   返回值类型    函数名(参数类型  形式参数1, 参数类型  形式参数2-) { ...

  3. [学习笔记]Java代码中各种类型变量的内存分配机制

    程序运行时,我们最好对数据保存到什么地方做到心中有数.特别要注意的是内存的分配.有六个地方都可以保存数据: (1) 寄存器 这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部.然而 ...

  4. 大数据学习笔记——Java篇之集合框架(ArrayList)

    Java集合框架学习笔记 1. Java集合框架中各接口或子类的继承以及实现关系图: 2. 数组和集合类的区别整理: 数组: 1. 长度是固定的 2. 既可以存放基本数据类型又可以存放引用数据类型 3 ...

  5. $.ajax函数调接口,报异常No converter found for return value of type: class java.util.ArrayList

    接口正常执行,返回给前端后报服务器500异常,异常详情: org.springframework.http.converter.HttpMessageNotWritableException: No ...

  6. java学习笔记之集合—ArrayList源码解析

    1.ArrayList简介 ArrayList是一个数组队列,与java中的数组的容量固定不同,它可以动态的实现容量的增涨.所以ArrayList也叫动态数组.当我们知道有多少个数据元素的时候,我们用 ...

  7. java学习笔记20(Arraylist复习,Collection接口方法,迭代器,增强型for循环)

    集合:集合是Java提供的一种容器,可以用来存储多个数据: 集合与数组的区别:集合的长度是可变的,数组的长度是固定的 集合中存储的数据必须是引用类型数据: ArrayList回顾: public cl ...

  8. Java集合---ArrayList的实现原理

    目录: 一. ArrayList概述 二. ArrayList的实现 1) 私有属性 2) 构造方法 3) 元素存储 4) 元素读取 5) 元素删除                 6) 调整数组容量 ...

  9. 一篇很好的学习查看Java源代码的文章

    目录: 一. ArrayList概述 二. ArrayList的实现 1) 私有属性 2) 构造方法 3) 元素存储 4) 元素读取 5) 元素删除                 6) 调整数组容量 ...

  10. JAVA中ArrayList用法

    JAVA中ArrayList用法 2011-07-20 15:02:03|  分类: 计算机专业 |  标签:java  arraylist用法  |举报|字号 订阅     Java学习过程中做题时 ...

随机推荐

  1. GO网络编程(二)

    [[Go语言系列视频]老男孩带你21周搞定Go语言[全 242]] https://www.bilibili.com/video/BV1fD4y117Dg/?p=113&share_sourc ...

  2. 一行命令使用 Docker 编译 Latex 文件,简单优雅

    使用 Docker 编译 LaTeX 文章 LaTeX 是一种常用的排版系统,它可以帮助用户创建漂亮.专业的文档.但是,安装和配置 LaTeX 比较麻烦,特别是对于初学者而言. Docker 是一个开 ...

  3. GetX 关于报错 Null check operator used on a null value的解决

    import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'logic.dart'; class Ge ...

  4. 在VS Code 中调试远程服务器的PHP代码

    背景 对于PHP的调试,一般来说我们用 echo 和 var_dump 就够用了. 有时会碰到要解决复杂的逻辑或需要确认代码的运行顺序,这里用var_dump效率就比较低了,这时建议用断点的方式进行代 ...

  5. 【调制解调】PM 调相

    说明 学习数字信号处理算法时整理的学习笔记.同系列文章目录可见 <DSP 学习之路>目录,代码已上传到 Github - ModulationAndDemodulation.本篇介绍 PM ...

  6. gin 接口开发 - 用户输入自动 TrimSpace

    最近在思考一个问题,针对用户的输入,能不能快速校验? 比方说下面的 struct,大家用过 gin 的就知道,支持指定某个字段为 required,用户如果不输入,就检验不通过. type Login ...

  7. NOIP模拟测试A3

    A. 谜之阶乘 题目是让我们把 \(n\) 分解成两个阶乘的商,本来想推个式子什么的,结果发现推不出来. 我们知道,阶乘的增长速率非常的快啊!那么这个 \(b - a\) 的值肯定不会太大,我们可以暴 ...

  8. Cilium系列-1-Cilium特色 功能及适用场景

    系列文章 Cilium 系列文章 Cilium 简介 Cilium 是一个开源的云原生解决方案,用于提供.保护(安全功能)和观察(监控功能)工作负载之间的网络连接,由革命性的内核技术 eBPF 提供动 ...

  9. MAUI中Windows的标题栏颜色怎么设置

    如下图所示,MAUI中Windows下的标题栏是灰色的,如何设置颜色,找了很久,在GitHub上的issue中找到了答案, 找到/Platforms/Windows/App.xaml <maui ...

  10. Java与PHP的区别

    1.PHP暂时不支持像Java那样的JIT运行时编译的热点代码,但PHP具有opcache机制,能够将脚本对应的opcode缓存在内存中. 补充:JIT与JVM的三种执行模式:解释模式.编译模式.混合 ...