IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java 基础篇--基础知识之集合ArrayList -> 正文阅读

[Java知识库]Java 基础篇--基础知识之集合ArrayList

ArrayList 简介

ArrayList 实现了List接口,是一个顺序(插入顺序)容器,允许存放null元素,底层通过数组实现的,可将其理解一个动态数组(容量自动增长)。ArrayList擅长随机访问,但在列表中间位置进行增、删元素操作效率较低。
ArrayList 不是线程安全的,多线程环境下可以考虑用Collections.synchronizedList(List list)函数返回一个线程安全的ArrayList类,也可以使用并发包下的CopyOnWriteArrayList类。

一、实现原理

ArrayList是完全基于Object类型数组实现的,内部提供了一个自动扩容机制来动态扩增数组容量。当我们进行对象元素添加的时,判断当前元素个数是否达到数组容量,达到了则进行数组扩容,扩容大小为原来的1.5倍或实际需要容量大小,然后将原数组中的元素复制到扩容后的新数组中,并且新数组替换元数组,最后进行新元素的添加。这样就完成了动态数组的实现。

二、源码分析

2.1 继承与实现关系

在这里插入图片描述
在这里插入图片描述

  • 实现了RandomAccess接口,标记着其支持随机快速访问;
  • 实现了Cloneable接口,标记着其可以被克隆复制;
  • 实现了Serializable接口,意味着它支持序列化;
  • 继承了AbstractList类,意味着它是List接口的具体实现,遵循着List的操作规范,共享一些通用数据操作。

2.2 重要成员信息

在这里插入图片描述

  • DEFAULT_CAPACITY:定义了ArrayList的默认初始化大小,当ArrayList的构造方法没有显示指定数组长度时,类内部使用该默认缺省值作为数组的容量大小;
  • EMPTY_ELEMENTDATA:共享的空Object数组实例,当ArrayList构造方法中显示指定数组长度为0时,类内部使用该值赋值给elemetData数组;
  • DEFAULTCAPACITY_EMPTY_ELEMENTDATA:共享的空Object数组实例,当ArrayList构造方法中没有显示指定数组长度时,类内部使用该值赋值给elemetData数组;注意:将其与EMPTY_ELEMENTDATA区分开来,以知晓添加第一个元素时扩容多少。
  • elemetData:ArrayList 的元素存储在其中的数组缓冲区,是ArrayList的底层数据结构,用于存放实际元素,被标记为transient,序列化的时候此字段不会被序列化;
  • size:ArrayList中实际存放的元素个数。
  • MAX_ARRAY_SIZE:ArrayList可分配的最大大小。

2.3 扩容机制

ArrayList在添加元素的时候,会触发扩容检测,当检测到当前的elementData容量已满,则进行扩容处理,然后再将新元素添加到elementData尾部。

  • 扩容源码:在这里插入图片描述
  • 扩容原理:
    1. 首先,它判断了元素个数是否等于当前数组的容量,也就是判断当前数组是不是满的,如果当前空间是满的,就需要扩容了,grow函数就是扩容函数了,扩容后再将被加元素加到数组中;
    2. 计算当前ArrayList的原容量,然后进行扩大到1.5倍并记作新容量;
    3. 若新容量等于或小于所需要的最小容量,空容量集合则返回默认容量与最小所需容量中最大值,否则返回最小所需容量;
    4. 若新容量等于或超过ArrayList的最大容量,则返回整数最大值或ArrayList的最大容量; 否则返回新容量。

注意:

  • elementData被赋予的是EMPTY_ELEMENTDATA,此时数组容量为0,添加元素时,会进入此扩容情况,容量从0扩展到1;
  • elementData被赋予的是DEFAULTCAPACITY_EMPTY_ELEMENTDATA,此时数组容量为0,添加元素时,会进入此扩容情况,容量从0扩展到10;
  • 当ArrayList的容量大于0,并且ArrayList是满的时,此时添加元素的话,进行正常扩容,每次扩容到原来的1.5倍。

2.4 快速失败(fast-fail)机制

快速失败(fast-fail)是Java集合中的一种错误机制。它只能被用来检测错误,因为JDK并不保证fail-fast机制一定会发生

  • 原理:迭代器在遍历时,直接访问集合中的内容,并且在遍历过程中使用一个modCount变量。集合在被遍历期间,如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。
  • 事件产生的条件:当多个线程对Collection进行操作时,若其中某一个线程通过iterator去遍历集合时,该集合的内容被其他线程所改变,则会抛出ConcurrentModificationException异常。
  • 解决办法:通过java.util.concurrent集合包下的相应类去处理,则不会产生fast-fail事件。

2.5 安全失败(fail-safe)

  • 原理:由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发Concurrent Modification Exception。
  • 采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。
  • 基于拷贝内容的优点是避免了Concurrent Modification Exception,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。
  • java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。

2.5 重要方法

2.5.1 添加

在这里插入图片描述
ArrayList在add(E e)方法中主要完成三件事:

  • 确保能够将元素添加到集合中,即确保ArrayList的容量(判断是否需要扩容);
  • 将元素扩容到elementData数组的指定位置;
  • ArrayList的实际元素个数加1。

ArrayList添加元素的方法还有:
在这里插入图片描述

  • add(int index, E element):在指定位置插入元素;在这里插入图片描述
  • addAll(Collection<? extends E> c):添加整个集合元素;在这里插入图片描述
  • addAll(int index, Collection<? extends E> c):在指定位置处插入集合元素;在这里插入图片描述

2.5.2 删除

在这里插入图片描述
remove(Object o)方法是移除指定元素。该方法主要是先找到待移除元素索引位置索引index,然后进行索引位置元素剔除。
ArrayList移除元素的方法还有:
在这里插入图片描述

  • remove(int index)方法的作用是删除指定下标的元素,并返回该索引处的元素;在这里插入图片描述
  • removeAll(Collection<?> c):删除包含在指定容器c中的所有元素;在这里插入图片描述
  • removeIf(Predicate<? super E> filter):按照一定规则过滤(删除)集合中的元素;

2.5.3 更新

在这里插入图片描述
set(int index, E element)方法是覆盖指定下标元素,也可以理解为是更新指定索引index处的元素。

2.5.4 查询

在这里插入图片描述
get(int index)方法返回指定索引的元素。

2.5.5 其他常用方法

  • retainAll(Collection<?> c):保留c中存在的元素,移除c中不存在的元素;
  • indexOf(Object o):正序查找首个为指定元素o的位置;
  • lastIndexOf(Object o):倒序查找首个为指定元素o的位置;
  • clear():清空集合;
  • subList(int fromIndex, int toIndex):创建只读子集合;
  • trimToSize():对ArrayList的容量进行调整为当前大小,减少数据空间;

三、对应线程安全实现

3.1 Collections 同步方法

synchronizedList(List list):返回一个SynchronizedList类型的线程安全的集合类。其对部分操作加上了synchronized关键字以保证线程安全。但其iterator()操作还不是线程安全的。其读写操作都加了同步关键字,读写操作都比较均匀;

3.2 CopyOnWriteArrayList

CopyOnWriteArrayList是java.util.concurrent包下面的一个实现线程安全的List。
其发生修改时候做copy操作,读的时候没有加任何同步关键字,做到了新老版本分离,保证读的高性能,适用于以读为主,读操作远远大于写操作的场景中使用,比如缓存。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-22 14:00:25  更:2021-07-22 14:03:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/18 17:43:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码