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()
代码表示
实践才是检验真理最好的方式:
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)); }