ArrayList 分析以及相关方法介绍

简介: java.util.ArrayList 是我们最常用的一个类,ArrayList 底层是动态数组,读者可以把它理解为数组的实现

ArrayList简介:

java.util.ArrayList 是我们最常用的一个类,ArrayList 底层是动态数组,读者可以把它理解为数组的实现

public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable{

}

如上代码我们可以看到 ArrayList 继承了 AbstractList() 抽象类,并实现了 List, RandomAccess, Cloneable, Serializable 接口

AbstractList :

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>{}

可以看到AbstractList 继承了 AbstractCollection 接口, 并实现了List 接口

AbstractCollection :

public abstract class AbstractCollection<E> implements Collection<E>{}

AbstractCollection 是一个抽象类,实现了Collection 接口,并提供了某些方法的具体实现。

Collection:

Collection 是一个顶级接口,是很多集合类的顶级接口,继承了Iterable ,支持轻量级遍历其中元素

public interface Collection<E> extends Iterable<E>{}

List :

ArrayList 实现了List接口,List 也是一个和Collection 媲美的顶级接口,继承了Collection 接口

public interface List<E> extends Collection<E>{}

它是许多集合类的父类,

eg:

List list = new ArrayList();

List list2 = new LinkedList();

RandomAccess

RandomAccess 也是一个顶级接口,实现了此接口的类支持随机访问

Cloneable

Cloneable 接口是一个顶级接口,实现了此接口的类支持浅拷贝

Serializable

实现此接口的类支持序列化的功能

ArrayList 相关方法介绍

0.jpg

1.jpg

trimToSize()

2.jpg


代码表示

实践才是检验真理最好的方式:

importjava.util.*;

/**
* 详述ArrayList 基本用法
*/
public class ArrayListTest{

private static class SortList implements Comparator<String>{

@Override
public int compare(String o1, String o2) {
Integeri1=Integer.valueOf(o1);
Integeri2=Integer.valueOf(o2);
if(i1<i2){
return-1;
}elseif(i1==i2){
return0;
}
return1;
}
}

// 使用可变参数,能够接受任意个参数
public Set<String> putSet(String...args){
Set<String> sets = new HashSet<>();
for(String str: args){
sets.add(str);
}
return sets;
}

public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("111");
list.add("222");

// 在指定位置添加元素
list.add(0,"333");
System.out.println(list);

// 进行外部排序
list.sort(newSortList());
System.out.println(list);

list.clear();
System.out.println(list.size());

// 使用addAll添加元素
ArrayList Testat = newArrayListTest();
list.addAll(at.putSet("1","2","3"));

Iterator<String> it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
// 移除所有元素
it.remove();
}

System.out.println("list是否为空 ? "+list.isEmpty());

list.add("111");
// 在指定位置添加一个set集合
list.addAll(0,at.putSet("1","2","3"));
System.out.println(list);

// 是否包含指定元素
if(list.contains("111")) {
list.remove("111");
}
System.out.println(list);

System.out.println(list.indexOf("1"));
// 注意subList()这个方法是左开右闭区间,Java 中很多都是类似的
System.out.println(list.subList(0,3));

// 扩大list的容量
list.ensureCapacity(10);
// 去掉list空闲的容量
list.trimToSize();

// 获取某个特定的元素
System.out.println(list.get(1));

// 创建一个list的双向链表
ListIterator<String> listIterator = list.listIterator();
while(listIterator.hasNext()){
// 移到list的末端
System.out.println(listIterator.next());
}
System.out.println("--------------------------");
while(listIterator.hasPrevious()){
// 移到list的首端
System.out.println(listIterator.previous());
}

// 把list转换为数组
Object[] objects = list.toArray();
System.out.println("objects = "+objects);

}
}


相关方法源码分析

分析源码还是要有代码的实例,跟进去理解每一行的意思,俗话说,有debug,不求人!

add()方法

/**
* Appends the specified element to the end of this list.
* 添加指定的元素在list的末尾
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/

// 假设第一次添加的是 "111"
public boolean add(E e) {
// size是0,所以size + 1 传的是1
ensureCapacityInternal(size+1); // Increments modCount!!
// elementData[0] = 111 , size++ = 1
elementData[size++] =e;
returntrue;
}

// 此方法用来进行list 扩容
private void ensureCapacityInternal(int minCapacity) {
// 此时elementData 并没有存储元素,为0
if(elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 则minCapacity 取默认初始容量和minCapacity 的最大值 (取1 和 10的最大值)
minCapacity=Math.max(DEFAULT_CAPACITY, minCapacity);
}
// 确保清晰的容量(最小容量与List元素的比较)
ensureExplicitCapacity(minCapacity);
}

// 在list中添加了一个元素,所以会导致结构化的修改,"结构化的修改"见下面解释
// 此时minCapacity 为 10
private void ensureExplicitCapacity(int minCapacity) {
// 次数 + 1
// 这个列表被修改结构的次数(比如添加和删除元素)会用modCount表示. 结构化修改是指的是能够
// 改变列表容量的操作,或者其他方式改变它,导致遍历的过程会产生错误的结果。
modCount++;

// overflow-conscious code
// 10 - 0 > 0 走grow 方法
if(minCapacity-elementData.length>0)
grow(minCapacity);
}

/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
* 增加容量确保容纳足够的元素
*
* @param minCapacity the desired minimum capacity
* 参数传过来的是10
*/
private void grow(int minCapacity) {
// overflow-conscious code
// oldCapacity = 0
intoldCapacity=elementData.length;
// newCapacity = 0
intnewCapacity=oldCapacity+(oldCapacity>>1);
// newCapacity - minCapacity = -10
if(newCapacity-minCapacity<0)
// newCapacity = 10
newCapacity=minCapacity;

// MAX_ARRAY_SIZE = 数组分配的最大空间 = 2147483639
// 一般情况下不会比 MAX_ARRAY_SIZE 还要大
if(newCapacity-MAX_ARRAY_SIZE>0)
newCapacity=hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
// 底层还是用的System.arraycopy(), 关于System.arrayCopy() 读者可以参考我的另一篇博客
elementData=Arrays.copyOf(elementData, newCapacity);
}

输出:

[333, 111, 222]

[111, 222, 333]

0

1

2

3

list是否为空 ? true

[1, 2, 3, 111]

[1, 2, 3]

0

[1, 2, 3]

2

1

2

3

--------------------------

3

2

1

objects = [Ljava.lang.Object;@6e8cf4c6

相关常用的基本数据类型包装类的值: Java基本数据类型包装类常用的值

add(int index, E element)


/**
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
* 在list中指定位置插入指定的元素,如果当前位置有元素,就移动当前位置的元素
* 要插入的位置的后面所有元素的位置向前 + 1
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
// 检查 0 这个位置是否越界
rangeCheckForAdd(index);

// 不再赘述,读者可以自行debug
ensureCapacityInternal(size+1); // Increments modCount!!
// 因为从当前位置插入元素,所以当前位置及后面的元素都会向后移动
// 使用System.arraycopy 进行数组复制
System.arraycopy(elementData, index, elementData, index+1,
size-index);
// 为当前元素赋值
elementData[index] =element;
size++;
}

/**
* A version of rangeCheck used by add and addAll.
* 为add 和 addall 提供的范围检查, 不符合条件,抛出IndexOutOfBoundsException 异常
*
*/
private void rangeCheckForAdd(intindex) {
if(index>size||index<0)
thrownewIndexOutOfBoundsException(outOfBoundsMsg(index));
}

            </div>
目录
相关文章
|
存储 Java Linux
TeamTalk - 蘑菇街开源的一款企业办公即时通信软件
TeamTalk 是蘑菇街开源的一款企业办公即时通信软件,最初是为自己内部沟通而做的 IM 工具。团队自己的介绍如下: 2013年我们蘑菇街从社区导购华丽转身时尚电商平台,为解决千万妹子和时尚卖家的沟通问题,我们开发了自己的即时通讯软件。既然已经有了用户使用的IM,为什么我们自己公司内部沟通还要用第三方的呢?因此就有了TT(TeamTalk)的雏形,现在蘑菇街内部的在线沟通全部通过TT来完成。随着TT功能的逐渐完善,我们决定把TT开源来回馈开源社区,希望国内的中小企业都能用上开源、免费、好用的IM工具!
1319 0
TeamTalk - 蘑菇街开源的一款企业办公即时通信软件
|
8月前
|
Java 数据库连接 应用服务中间件
JavaWeb CRUD 与分页系统架构学习教程
本教程详细讲解了如何使用 Java Web 技术构建一个带有 CRUD 和分页功能的应用程序。以产品信息管理为例,采用 MVC 架构设计,涵盖 Servlet、JSP、JDBC/MyBatis 等技术。内容包括基础知识介绍、项目结构划分、数据库连接配置、DAO 层实现、Service 层设计、Servlet 控制层编写、JSP 前端展示以及分页功能的实现。同时涉及日志配置和 Tomcat 部署运行。通过分层开发,确保代码清晰、职责分明,便于维护和扩展。适合初学者掌握 Java Web 开发全流程,并为学习更高级框架奠定基础。
237 0
|
Java 编译器 程序员
Java面试高频题:用最优解法算出2乘以8!
本文探讨了面试中一个看似简单的数学问题——如何高效计算2×8。从直接使用乘法、位运算优化、编译器优化、加法实现到大整数场景下的处理,全面解析了不同方法的原理和适用场景,帮助读者深入理解计算效率优化的重要性。
243 6
|
存储 编译器 C语言
【ARM汇编速成】零基础入门汇编语言之C与汇编混合编程(四)
【ARM汇编速成】零基础入门汇编语言之C与汇编混合编程(四)
415 0
【ARM汇编速成】零基础入门汇编语言之C与汇编混合编程(四)
|
存储 SQL Apache
Apache Doris 助力网易严选打造精细化运营 DMP 标签系统
Apache Doris 助力网易严选打造精细化运营 DMP 标签系统
708 0
|
传感器 C# 监控
硬件交互新体验:WPF与传感器的完美结合——从初始化串行端口到读取温度数据,一步步教你打造实时监控的智能应用
【8月更文挑战第31天】本文通过详细教程,指导Windows Presentation Foundation (WPF) 开发者如何读取并处理温度传感器数据,增强应用程序的功能性和用户体验。首先,通过`.NET Framework`的`Serial Port`类实现与传感器的串行通信;接着,创建WPF界面显示实时数据;最后,提供示例代码说明如何初始化串行端口及读取数据。无论哪种传感器,只要支持串行通信,均可采用类似方法集成到WPF应用中。适合希望掌握硬件交互技术的WPF开发者参考。
345 0
|
Android开发 Shell
Appium之ADB指令详解
前言 学Android测试,ADB指令是必学的。 图1 一、ADB概述        Android Debug Bridge,Android调试桥接器,简称adb,是用于管理模拟器或真机状态的万能工具,采用了客户端-服务器模型,包括三个部分:        1、客户端部分,运行在开发用的电脑上,可以在命令行中运行adb命令来调用该客户端,像ADB插件和DDMS这样的Android工具也可以调用adb客户端。
1887 0
|
搜索推荐 数据可视化 项目管理
好用、强大的大纲编辑器综合评测:Workflowy、 Dynalist 、 幕布、 Cloud Outliner 、 坚果云大纲笔记、 双链笔记、 大纲模式软件
好用、强大的大纲编辑器综合评测:Workflowy、 Dynalist 、 幕布、 Cloud Outliner 、 坚果云大纲笔记、 双链笔记、 大纲模式软件 最近几年,大纲编辑器作为特殊的编辑器,逐渐被很多用户所知悉。其中,支持将大纲一键转换为思维导图的幕布可能最为有名。 那么,对于笔记用户而言,是否需要选用一款大纲编辑器? 我将分析大纲编辑器的基本功能、分类、优点和缺点,以便用户更好地把握大纲编辑器的特点。然后,再推荐几款强大、好用的大纲编辑器。 关于大纲编辑器的具体分析比较多。如果只是期待查看值得推荐的大纲软件的话,建议直接跳转至本文最后一部分。
2345 0
好用、强大的大纲编辑器综合评测:Workflowy、 Dynalist 、 幕布、 Cloud Outliner 、 坚果云大纲笔记、 双链笔记、 大纲模式软件
|
运维 监控 Java
使用蓝鲸自愈平台完成java项目程序的自愈机制
使用蓝鲸自愈平台完成java项目程序的自愈机制 1.蓝鲸自愈平台 故障自愈是行业领先的"故障自动化处理"解决方案,提升企业的服务可用性和降低故障处理的人力投入,实现故障自愈从"人工处理"到"无人值守"的变革! 自愈平台可以根据连接配置好的监控平台,当收到我们指定要自愈的监控告警时,首先筛选出告警信息的ip地址,再匹配该服务器所在的集群节点,确认服务器信息,然后将服务器地址传到对应的作业平台的某个作业里,通过作业的具体恢复脚本,实现项目的故障资源机制。
787 0
使用蓝鲸自愈平台完成java项目程序的自愈机制