当前位置: 首页 > news >正文

深度解析ArrayList使用

在这里插入图片描述

文章目录

  • 一、ArrayList是什么?
  • 二、ArrayList的构造方法
  • 三、ArrayList的常见方法
    • 常见方法
    • 遍历ArrayList
    • 使用迭代器删除元素
  • 四、ArrayList的扩容机制

一、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进行扩容

相关文章:

  • 吴恩达深度学习笔记(六)——超参数调试、Batch正则化和程序框架
  • 【甄选靶场】Vulnhub百个项目渗透——项目十六:FristiLeaks_1.3(文件上传,py脚本改写,sudo提权,脏牛提权,源码获取)
  • 苹果iPhone手机iOS16如何取消关闭复制粘贴时不停弹出的剪贴板粘贴提示通知弹窗?
  • Android移动应用开发之ImageView、ProgressBar和Notification的一些简单使用
  • SQL经典练习题(openGauss数据库)上
  • CSDN编程竞赛-第六期(下)
  • Spring 静态属性赋值 @value 注入静态属性 @Value注解用法
  • 【零基础学QT】第九章 窗口美化QSS的使用
  • aws codesuit workshop
  • Linux内存管理——段页式访问
  • Hadoop基础学习笔记
  • 微信小程序 - 页面插入添加 Banner 广告超详细教程(支持自定义样式、位置、大小等)及注意事项
  • JavaScript笔记9-节点操作
  • 【YOLOv7】使用 YOLOv7 做目标检测 (使用自己的数据集 + 图解超详细)
  • 【C语言】break 关键字
  • 网络传输文件的问题
  • [译]如何构建服务器端web组件,为何要构建?
  • 【RocksDB】TransactionDB源码分析
  • 2017 年终总结 —— 在路上
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • Android开源项目规范总结
  • ECS应用管理最佳实践
  • java8 Stream Pipelines 浅析
  • SpiderData 2019年2月25日 DApp数据排行榜
  • Vue.js-Day01
  • 编写符合Python风格的对象
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 二维平面内的碰撞检测【一】
  • 分享几个不错的工具
  • 让你的分享飞起来——极光推出社会化分享组件
  • 思考 CSS 架构
  • 硬币翻转问题,区间操作
  • 云大使推广中的常见热门问题
  • 带你开发类似Pokemon Go的AR游戏
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • (19)夹钳(用于送货)
  • (PySpark)RDD实验实战——求商品销量排行
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)ssm码农论坛 毕业设计 231126
  • (接口自动化)Python3操作MySQL数据库
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (五)Python 垃圾回收机制
  • (已解决)Bootstrap精美弹出框模态框modal,实现js向modal传递数据
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • ****** 二 ******、软设笔记【数据结构】-KMP算法、树、二叉树
  • .apk文件,IIS不支持下载解决
  • .NET Framework 4.6.2改进了WPF和安全性
  • .net framework 4.8 开发windows系统服务
  • .NET/C#⾯试题汇总系列:集合、异常、泛型、LINQ、委托、EF!(完整版)
  • .net8.0与halcon编程环境构建
  • /run/containerd/containerd.sock connect: connection refused
  • [Android]使用Retrofit进行网络请求
  • [AutoSar]工程中的cpuload陷阱(三)测试
  • [BZOJ] 2044: 三维导弹拦截