学习一下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学习过程中做题时 ...
随机推荐
- 2022蓝桥杯B组(java)版
2022蓝桥杯b组 A题 import java.math.BigInteger; public class A { public static void main(String[] args) { ...
- Flutter系列文章-Flutter环境搭建和Dart基础
Flutter是Google推出的一个开源的.高性能的移动应用开发框架,可以用一套代码库开发Android和iOS应用.Dart则是Flutter所使用的编程语言.让我们来看看如何搭建Flutter开 ...
- 春节无法线下社交聚会,来线上“一起X”共享体验
引语: 共享体验或许是全真互联网时代最显著的标志. 被疫情深刻改变的一年里,人们的社交关系和社交活动正在发生巨大的改变. 一方面,从线下转线上,我们能通过互联网连接更多的人,参与各种形式的社交活动,将 ...
- JVM方法区
JVM方法区 <Java虚拟机规范>中明确说明:"尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩."但对于HotSpo ...
- debian11使用kubeadm安装k8s
前言 节点信息: master1:192.168.0.33 node1:192.168.0.31 node2:192.168.0.32 版本: 系统:debian11 64bit linux内核:5. ...
- 何时使用MongoDB而不是MySql
什么是 MySQL 和 MongoDB MySQL 和 MongoDB 是两个可用于存储和管理数据的数据库管理系统.MySQL 是一个关系数据库系统,以结构化表格格式存储数据.相比之下,MongoDB ...
- Linux cpu 亲缘性 绑核
前言 https://www.cnblogs.com/studywithallofyou/p/17435497.html https://www.cnblogs.com/studywithallofy ...
- trino on yarn
一.前言 最近在研究trino on yarn 功能,网上大部分都是关于presto on yarn文章,关于trino on yarn 资料很少,但是本质上差不多,需要修改一些内容比,主要在调试方面 ...
- MindSponge分子动力学模拟——定义一个分子系统(2023.08)
技术背景 在前面两篇文章中,我们分别介绍了分子动力学模拟软件MindSponge的软件架构和安装与使用教程.这里我们进入到实用化阶段,假定大家都已经在本地部署好了基于MindSpore的MindSpo ...
- Linux文件管理知识查找文件(第二篇)
Linux文件管理知识:查找文件(第二篇) 上篇文章详细介绍了linux系统中查找文件的工具或者命令程序locate和find命令的基本操作.那么,今天这篇文章紧接着查找文件相关操作内容介绍. Fin ...