深度解析Java中ArrayList的使用
作者:熬夜磕代码丶 发布时间:2023-06-16 23:26:01
一、ArrayList是什么
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。ArrayList 继承了 AbstractList ,并实现了 List 接口。
我们发现ArrayList类位于java.util包中,使用之前需要去引入它.
import java.util.ArrayList;
ArrayList如何定义:
ArrayList<E> arrayList = new ArrayList<E>();
此数E为泛型实参类型,只能为引用数据类型,ArrayList想存储什么类型的数据,我们就传什么就可以。
List<E> list = new ArrayList<E>();
因我们的ArrayList是继承于List的,所以我们可以用父类去接受子类对象,向上转型。
二、ArrayList的构造方法
我们发现ArrayList一共提供了三种构造方法。
构造方法1:
构造一个空的顺序表
List<Integer> list = new ArrayList<>();
构造方法2:
构造一个指定大小为5的顺序表
List<Integer> list = new ArrayList<>(5);
构造方法3:
此处传入的要么是自己本身类型,或者是子类类型。
此处构造一个和list2元素一致的顺序表
List<Integer> list2 = new ArrayList<>(5); List<Integer> list = new ArrayList<>(list2);
初始时的坑
List list = new ArrayList();
这样对顺序表进行初始化的话,没有指定任何类型,这样的话可以存放任意类型的元素,这样会存在很大的安全隐患。
三、ArrayList的常见方法
常见方法
在我的上一篇实现顺序表中,已经把大多数方法手动实现了一遍,此处我在说明几个重点的。
remove方法
ArrayList提供给我们两个remove方法
一个是传入要删除的下标,一个是要删除的引用。
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(10);
list.add(8);
list.remove(1);
System.out.println(list);
}
如果我们传入的是int类型那么我们删除的是该下标的数据。
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(10);
list.add(8);
list.remove(new Integer(10));
System.out.println(list);
}
如果我们传入的是引用数据类型,那么将删除该顺序表中的该引用数据。
subList方法
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
System.out.println("截取之前的list:"+list);
List<Integer> list1 = list.subList(1,3);
list1.set(0,5);
System.out.println("截取之后的list:"+list);
}
为啥改了list1之后,list的数据也发生了变化。
因为在截取之后并没有复制一份内容给list1,而是指向同一块内容。
遍历ArrayList
方法1:
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i)+" ");
}
System.out.println();
}
方法2:
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
for (Integer x:list) {
System.out.print(x+" ");
}
System.out.println();
}
方法3:
使用迭代器
方法 | 作用 |
---|---|
.next() | 返回迭代器写一个元素,更新迭代器状态 |
.hasNext() | 检测集合中是否还有元素 |
.remove() | 将迭代器返回的元素删除 |
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
Iterator<Integer> it = list.listIterator();
while (it.hasNext()) {
System.out.print(it.next()+" ");
}
System.out.println();
}
使用迭代器删除元素
我们删除集合小于3的元素
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
Iterator<Integer> it = list.listIterator();
while (it.hasNext()) {
if(it.next() < 3) {
it.remove();
}
}
System.out.println(list);
}
迭代器的remove方法只能删除当前指向的元素。
四、ArrayList的扩容机制
List<Integer> list = new ArrayList<>();
很多资料都在说这样初始化一个集合,说默认大小为10,那事实到底是不是如此呢?我们一步步查看源码一探究竟。
我们发现当前引用指向后面那个引用
我们发现这里的引用是一个空引用,初始集合时,是一个空集合。
那如何扩容呢?
既然我们的顺序表是空的,那如何add呢?
如果是无参构造的话,就传一个默认大小和传入大小的最大值。
我们可以发现如果大于数组大小时,就会grow。
我们可以发现计算一个新容量,和我们传入的大小做比较,如果新容量小于传入的大小时,指定当前集合大小为传入的大小。否则,对集合大小进行1.5倍扩容。
但如果我们1.5倍扩容的大小超过了这个指定的范围2147483639时
系统会报一个内存溢出异常。
1. 检测是否真正需要扩容,如果是调用grow准备扩容
2. 预估需要库容的大小
初步预估按照1.5倍大小扩容
如果用户所需大小超过预估1.5倍大小,则按照用户所需大小扩容
真正扩容之前检测是否能扩容成功,防止太大导致扩容失败
3. 使用copyOf进行扩容
来源:https://blog.csdn.net/buhuisuanfa/article/details/126926645
![](https://www.aspxhome.com/images/zang.png)
![](https://www.aspxhome.com/images/jiucuo.png)
猜你喜欢
- 最近几年玩得最疯狂的应该是发红包了,尤其是过年的时候特别受欢迎,下面写了红包的随机算法,其实挺简单的,仅是提供一种思路,希望可以给大家一些启
- 在Android Studio中对一个自己库进行生成操作时将会同时生成*.jar与*.aar文件。分别存储位置: &n
- 前言服务消费者调用服务提供者的时候使用RestTemplate技术存在不便之处:拼接urlrestTmplate.getForObJect这
- 本文实例讲述了Android中TextView显示插入的图片实现方法。分享给大家供大家参考,具体如下:Android系统默认给TextVie
- 在没介绍正文之前,先给大家介绍下websocket的背景和原理:背景在浏览器中通过http仅能实现单向的通信,comet可以一定程度上模拟双
- 本文实例讲述了Android编程之消息机制。分享给大家供大家参考,具体如下:一、角色描述1.Looper: 一个线程可以产生一个Looper
- 本文实例为大家分享了android TextView跑马灯效果的具体代码,供大家参考,具体内容如下一、要点设置四个属性android:sin
- 一、链表1.1 概述链表是真正动态的数据结构,最简单的动态数据结构,基本用于辅助组成其他数据结构。数据存储在“节点”(Node)中优点:真正
- 引言一个复杂的分布式系统,用户发起一个请求,这个请求可能调用几十到几百个服务,经过很多业务层,而每个业务又是多个机器集群,一个请求具体被随机
- 前言回想一下,在学Java时接触的正则表达式,其实Kotlin中也是类似。只不过使用Kotlin 的语法来表达,更为简洁。正则(Regex)
- 概述什么是动态编程?动态编程解决什么问题?Java中如何使用?什么原理?如何改进?(需要我们一起探索,由于自己也是比较菜,一般深入不到这个程
- 本文实例讲述了Java后台线程操作。分享给大家供大家参考,具体如下:一 点睛有一种线程,它是后面运行的,它的任务是为其他线程提供服务,这种线
- 一、JVM 内存模型根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。1、虚拟机栈:每个线程有一个
- 本文介绍了Java实现动态获取图片验证码的示例代码,分享给大家,具体如下:import javax.imageio.ImageIO;impo
- 本文基于SpringBoot 2.5.0-M2讲解Spring中Lifecycle和SmartLifecycle的作用和区别,以及如何控制S
- 今天没有继续学习新知识点,画出了一个随鼠标画出的 图形,知识点全都是之前学的,话不多说,先上图:代码部分: // ope
- 唉!我还真是在面试中学习新东东啊,一个公司刚刚给了个测试,不过我很奇怪的是为什么web developer的职位居然考java的反射机制题,
- 1.准备工作第一步就是先要注册一个支付宝的账号(注册这里不说,不是重点),然后登入官方首页,去到应用列表里面找到沙箱应用。基本信息的APPI
- 一,使用注解: 在spring的配置文件applicationContext.xml中,加入注解扫描。配
- 目录操作创建目录File类中有两个方法可以用来创建文件夹:mkdir( )方法创建一个文件夹,成功则返回true,失败则返回false。失败