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>
目录
相关文章
|
SQL 数据采集 存储
基于clickhouse做用户画像,标签圈选
基于clickhouse做用户画像,标签圈选
1573 0
基于clickhouse做用户画像,标签圈选
|
Android开发 索引 容器
【Android 应用开发】Android 组件 位置坐标 属性 ( 组件位置属性 | 父容器坐标系坐标 | 窗口坐标系坐标 | 屏幕坐标系坐标 | 触摸坐标 )
【Android 应用开发】Android 组件 位置坐标 属性 ( 组件位置属性 | 父容器坐标系坐标 | 窗口坐标系坐标 | 屏幕坐标系坐标 | 触摸坐标 )
518 0
|
设计模式 SQL JSON
谷粒商城笔记+踩坑(8)——仓库管理
采购单维护-采购需求、 采购单维护-采购单、 仓库维护、商品库存:
谷粒商城笔记+踩坑(8)——仓库管理
|
设计模式 开发框架 开发工具
深入理解移动应用开发:从概念到实践
【9月更文挑战第30天】在这篇文章中,我们将深入探讨移动应用开发的各个方面。我们将从移动应用开发的基本概念开始,然后逐步深入到具体的技术实现。我们将讨论移动操作系统的基础知识,包括Android和iOS的架构和特性。然后,我们将深入探讨移动应用开发的关键技术,包括编程语言、开发框架和应用设计模式。我们还将提供一些代码示例,以帮助读者更好地理解和掌握这些概念和技术。最后,我们将讨论移动应用开发的未来趋势和挑战。
323 6
|
移动开发 JavaScript 数据可视化
|
Web App开发 移动开发 前端开发
display: inline-block 可以在不同的浏览器中正常工作吗?
【10月更文挑战第27天】`display: inline-block`在现代浏览器中能够正常工作,但在旧版本浏览器中可能会存在兼容性问题。在实际的网页开发中,需要根据目标用户群体所使用的浏览器情况,合理地选择解决兼容性问题的方法,以确保页面在各种浏览器环境下都能够呈现出一致的布局效果。
|
存储 SQL 分布式计算
物联网数据库 IoTDB 解析
Apache IoTDB 是专为物联网时序数据打造的数据库,提供数据采集、存储、分析的功能。IoTDB 提供端云一体化的解决方案,在云端,提供高性能的数据读写以及丰富的查询能力,针对物联网场景定制高效的目录组织结构,并与 Apache Hadoop、Spark、Flink 等大数据系统无缝打通;在边缘端,提供轻量化的 TsFile 管理能力,端上的数据写到本地 TsFile,并提供一定的基础查询能力,同时支持将 TsFile 数据同步到云端。
6693 102
|
存储 边缘计算 运维
阿里云全球基础设施布局与基础设施科技创新介绍
本文介绍了阿里云全球基础设施布局与基础设施科技创新,包含公共云地域、超级数据中心、基础设施四层形态、数据中心、服务器、网络、解决方案科技创新专题等内容。
2198 0
阿里云全球基础设施布局与基础设施科技创新介绍
|
消息中间件 RocketMQ
RocketMq名词概念
RocketMq名词概念
359 0
|
安全 网络协议 Java
Spring Security-退出登录和CSRF
Spring Security-退出登录和CSRF
Spring Security-退出登录和CSRF