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>
目录
相关文章
|
算法 Dubbo NoSQL
Java中5种List的去重方法及它们的效率对比,你用对了吗?
01、使用两个for循环实现List去重(有序) /**使用两个for循环实现List去重(有序) * * @param list * */ public static List removeDuplicationBy2For(List<Integer> list) { for (int i=0;i<list.size();i++) { for (int j=i+1;j<list.size();j++) { if(list.get(i).equa
24451 2
Java中5种List的去重方法及它们的效率对比,你用对了吗?
|
28天前
|
存储 Java API
从源码角度解析ArrayList.subList的几个坑!
从源码角度解析ArrayList.subList的几个坑!
|
28天前
|
存储 Java 编译器
Collection-ArrayList源码解析
Collection-ArrayList源码解析
14 0
|
3月前
|
存储 Java 数据处理
如何使用 Java 迭代 HashMap 中的 ArrayList
【8月更文挑战第23天】
48 2
|
6月前
|
存储 安全 Java
基于ArrayList源码探讨如何使用ArrayList
基于ArrayList源码探讨如何使用ArrayList
|
11月前
|
C#
C# 集合(ArrayList)的方法和使用
C# 集合(ArrayList)的方法和使用
|
存储 Java API
ArrayList类【JDK源码分析】
ArrayList类【JDK源码分析】
49 0
|
Java
ArrayList 分析以及相关方法介绍
java.util.ArrayList 是我们最常用的一个类,ArrayList 底层是动态数组,读者可以把它理解为数组的实现
104 0
ArrayList 分析以及相关方法介绍
|
存储
ArrayList的retainAll()方法使用
retainAll()方法:list1.retainAll(list2),即list1调用retainAll()方法得到list1和list2的交集并存储在list1中,这个方法的返回值是boolean型,true代表方法执行成功。 @Test public void test1() { ArrayList arrayList1 = new ArrayList(); arrayList1.add(123); arrayList1.add.
278 0
|
存储 Java 容器
Java中ArrayList,LinkedList,Vector三者的异同点及其使用场景和ArrayList的一些常用方法
相同点:三者存储的都是有序,可重复的数据。 异:①:ArrayList底层存储类型树Object数组,而LinkedList底层是双向链表 ②:ArrayList和Vector调用创建空参构造器创建对象时,默认的size是10,但是当自动扩容的时候,ArrayList扩容为当前容器size的1.5倍,而Vector自动扩容为当前的2倍。 使用场景:①:当查找操作比较多时,使用ArrayList,因为其底层是数组实现,可以根据角标查找,时间复杂度是O(1),而LinkedList底层是双向...
135 0