学习一下Java的ArrayList和contains函数和扩容机制
起因
在Leetcode上做题写了两种暴力解法,但是执行效率上不太一样。

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

null和object区分开来还是因为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函数和扩容机制的更多相关文章
- 浅谈JAVA中HashMap、ArrayList、StringBuilder等的扩容机制
JAVA中的部分需要扩容的内容总结如下:第一部分: HashMap<String, String> hmap=new HashMap<>(); HashSet<Strin ...
- [java学习笔记]java语言基础概述之函数的定义和使用&函数传值问题
1.函数 1.什么是函数? 定义在类中的具有特定功能的一段独立小程序. 函数也叫做方法 2.函数的格式 修饰符 返回值类型 函数名(参数类型 形式参数1, 参数类型 形式参数2-) { ...
- [学习笔记]Java代码中各种类型变量的内存分配机制
程序运行时,我们最好对数据保存到什么地方做到心中有数.特别要注意的是内存的分配.有六个地方都可以保存数据: (1) 寄存器 这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部.然而 ...
- 大数据学习笔记——Java篇之集合框架(ArrayList)
Java集合框架学习笔记 1. Java集合框架中各接口或子类的继承以及实现关系图: 2. 数组和集合类的区别整理: 数组: 1. 长度是固定的 2. 既可以存放基本数据类型又可以存放引用数据类型 3 ...
- $.ajax函数调接口,报异常No converter found for return value of type: class java.util.ArrayList
接口正常执行,返回给前端后报服务器500异常,异常详情: org.springframework.http.converter.HttpMessageNotWritableException: No ...
- java学习笔记之集合—ArrayList源码解析
1.ArrayList简介 ArrayList是一个数组队列,与java中的数组的容量固定不同,它可以动态的实现容量的增涨.所以ArrayList也叫动态数组.当我们知道有多少个数据元素的时候,我们用 ...
- java学习笔记20(Arraylist复习,Collection接口方法,迭代器,增强型for循环)
集合:集合是Java提供的一种容器,可以用来存储多个数据: 集合与数组的区别:集合的长度是可变的,数组的长度是固定的 集合中存储的数据必须是引用类型数据: ArrayList回顾: public cl ...
- Java集合---ArrayList的实现原理
目录: 一. ArrayList概述 二. ArrayList的实现 1) 私有属性 2) 构造方法 3) 元素存储 4) 元素读取 5) 元素删除 6) 调整数组容量 ...
- 一篇很好的学习查看Java源代码的文章
目录: 一. ArrayList概述 二. ArrayList的实现 1) 私有属性 2) 构造方法 3) 元素存储 4) 元素读取 5) 元素删除 6) 调整数组容量 ...
- JAVA中ArrayList用法
JAVA中ArrayList用法 2011-07-20 15:02:03| 分类: 计算机专业 | 标签:java arraylist用法 |举报|字号 订阅 Java学习过程中做题时 ...
随机推荐
- 【RabbitMQ】当队列中消息数量超过最大长度的淘汰策略
[RabbitMQ]当队列中消息数量超过最大长度的淘汰策略 说明 最近在研究RabbitMQ如何实现延时队列时发现消息进入死信队列的情况之一就是当消息数量超过队列设置的最大长度时会被丢入死信队列,看到 ...
- Lucene.Net -全文检索引擎
简介 Lucene.Net只是一个全文检索开发包,不是一个成型的搜索引擎,它的功能就是负责将文本数据按照某种分词算法进行切词,分词后的结果存储在索引库中,从索引库检索数据的速度灰常快 版本使用 3.0 ...
- 2023-07-31:用r、e、d三种字符,拼出一个回文子串数量等于x的字符串。 1 <= x <= 10^5。 来自百度。
2023-07-31:用r.e.d三种字符,拼出一个回文子串数量等于x的字符串. 1 <= x <= 10^5. 来自百度. 答案2023-07-31: 大体步骤如下: 1.初始化一个字符 ...
- pylink
1.https://github.com/square/pylink/pull/72
- 记一次 .NET某报关系统 非托管泄露分析
一:背景 1. 讲故事 前段时间有位朋友找到我,说他的程序内存会出现暴涨,让我看下是怎么事情?而且还告诉我是在 Linux 环境下,说实话在Linux上分析.NET程序难度会很大,难度大的原因在于Li ...
- The database operation was expected to affect 1 row(s), but actually affected 0 row(s); 解决乐观并发
The database operation was expected to affect 1 row(s), but actually affected 0 row(s); 解决乐观并发 1.乐观并 ...
- 【双系统】Win10/Win11 引导 Ubuntu
目录 纲要 注意 写在最前 1. Win 分区 2. Ubuntu刻盘 3. 安装 Ubuntu 4. 配置引导 纲要 本文主要介绍了如何在已安装 Win10/Win11 前提下安装 Ubuntu 双 ...
- 一次搞定:借助Hutool封装代码快速解决webservice调用烦恼
前言 相信很多同行哪怕学了许多主流技术,但工作上依然免不了和传统企业打交道,而这样的企业往往还在用webservice做接口交互. 本文是作者近两年和医疗行业的厂家打交道研究出来的一点调用webser ...
- Stack Overflow开发者调查发布:AI将如何协助DevOps
Stack Overflow 发布了开创性的2023年度开发人员调查报告 [1].报告对 90,000 多名开发人员进行了调查,全面展示了当前软件开发人员的体验.接下来,本文将重点介绍几项重要发现,即 ...
- [超详细]SpringBoot整合WebSocket
1. 什么是WebSocket? WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它允许在浏览器和服务器之间进行实时的.双向的通信.相对于传统的基于请求和响应的 HTTP 协议, ...