ArrayList相关方法介绍及源码分析

目录ArrayList简介:ArrayList相关方法介绍代码表示相关方法源码分析ArrayList简介:java.util.ArrayList是我们最常用的一个类,ArrayList底层是动态数组,读者可以把它理解为数组的实现publicclassArrayList<E>extendsAbstractList<E>implementsList<E>,Rando...

ArrayList相关方法介绍及源码分析

目录

    • 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 相关方法介绍

trimToSize()

代码表示

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

import java.util.*;/** * 详述ArrayList 基本用法 */public class ArrayListTest { private static class SortList implements Comparator<String> {  @Override  public int compare(String o1, String o2) {Integer i1 = Integer.valueOf(o1);Integer i2 = Integer.valueOf(o2);if(i1 < i2){ return -1;}else if(i1 == i2){ return 0;}return 1;  } } // 使用可变参数,能够接受任意个参数 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(new SortList());  System.out.println(list);  list.clear();  System.out.println(list.size());  // 使用addAll添加元素  ArrayListTest at = new ArrayListTest();  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()方法

解释:添加指定的元素在list的末尾

 /**  * 添加指定的元素在list的末尾  */ // 假设第一次添加的是 “111“ public boolean add(E e) {  // size是0,所以size1 传的是1  ensureCapacityInternal(size1);   // elementData[0] = 111 , size= 1  elementData[size  ] = e;  return true; }  // 此方法用来进行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); } /**  * 增加容量确保容纳足够的元素  *   * 参数传过来的是10  */ private void grow(int minCapacity) {  // overflow-conscious code  // oldCapacity = 0  int oldCapacity = elementData.length;  // newCapacity = 0  int newCapacity = oldCapacity(oldCapacity >> 1);  // newCapacity - minCapacity = -10  if (newCapacity - minCapacity < 0)// newCapacity = 10newCapacity = 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); } 

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

add(int index, E element)

解释:在list中指定位置插入指定的元素,如果当前位置有元素,就移动当前位置的元素

  /**  * 在list中指定位置插入指定的元素,如果当前位置有元素,就移动当前位置的元素  * 要插入的位置的后面所有元素的位置向前1  *  */ public void add(int index, E element) {  // 检查 0 这个位置是否越界  rangeCheckForAdd(index);  // 不再赘述,读者可以自行debug  ensureCapacityInternal(size1);  // Increments modCount!!  // 因为从当前位置插入元素,所以当前位置及后面的元素都会向后移动  // 使用System.arraycopy 进行数组复制  System.arraycopy(elementData, index, elementData, index1,  
源文地址:https://www.guoxiongfei.cn/cntech/18359.html