介绍 List表示有顺序的集合,implements Cloneable扩展了基本方法, RandomAccess 标记接口,表示此类能随机访问,类似数组特性, 对象是连续存储的,根据索引直接定位到元素,访问效率高,LinkedList不能随机访问。继承AbstractList抽象类可以实现一些默认方法。
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable数据特性 内部是动态数组,根据索引访问效率高。插入和删除元素的效率低,因为需要移动元素,线程不安全。
1.基本使用方法介绍
public boolean add (E e)//添加元素到末尾 public boolean isempty ()//判断是否为空 public int size () //获取长度 public E get ( int index)//访问指定位置的元素 public int indexof (object o)//查找元素, 如果找到, 返回索引位置, 否则返回 - 1 public int astindexof (Object o)//从后往前找 public boolean contains (Object o)//是否包含指定元素,依据是equa1s方法的返回值 public E remove ( int index)//删除指定位置的元素,返回值为被删对象 //删除指定对象,只删除第一个相同的对象,返回值表示是否删除了元素 //如果。为nu11, 则删除值为nu11的元素 public boolean remove (Object o) public void clear ()//删除所有元素 //在指定位置插入元素, index为0表示插入最前面, index为 Arraylist的长度表示插到最后面 public void add ( int index, E element) public E set ( int index, E element)//修改指定位置的元素内容2.基本原理
内部一个elementData数组,一般有一些预留的空间,有一个整数size记录实际元素的个数, 各种public方法内部是基本是操作这个数组和元素个数,随着elementData实际元素个数的增多重新分配,size记录元素个数
transient Object[] elementData; private int size;add()添加容量10的原理,首先调用ensureCapacityInternal确保数组容量是否够,判断数组是不是空,是空,首先分配DEFAULT_CAPACITY默认值10容量,不是空数组调用ensureExplicitCapacity,grow方法扩容。
//首先调用ensureCapacityInternal确保数组容量是否够 public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { //判断数组是不是空,是空,首先分配DEFAULT_CAPACITY默认值10容量, // 不是空调用ensureExplicitCapacity,grow方法扩容。 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { //表示增加修改次数, modCount++; if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { //原数组长度 int oldCapacity = elementData.length; //右移一位相当于除以2,所以newCapacity相当于oldCapacity的1.5倍,10+5 int newCapacity = oldCapacity + (oldCapacity >> 1); //如果扩展了1.5倍小于minCapacity增加容量,就扩展minCapacity if (newCapacity - minCapacity < 0) newCapacity = minCapacity; elementData = Arrays.copyOf(elementData, newCapacity); }3.集合遍历使用 foreach的使用,编译器会转换成Iterator 迭代器的使用。
//foreach背后实现,编译器会转换成迭代器接口 for (Integer integer : list) { System.out.println(integer); } //获取new Itr();实现类对象 Iterator<Integer> iterator = list.iterator(); //判断是否还有元素未访问,next返回下一个元素 while (iterator.hasNext()){ System.out.println(iterator.next()); }ListIterator接口扩展了Integer接口
public ListIterator<E> listIterator(int index){ return new ListItr(index); } public ListIterator<E> listIterator(){ return new ListItr(index); }listItr对象,增加一些方法、向前遍历、添加元素等方法
private class ListItr extends Itr implements ListIterator<E> { ListItr(int index) public boolean hasPrevious() public int nextIndex() public int previousIndex() public E previous() public void set(E e) public void add(E e) }在迭代会报错,例如在遍历的时候调用容器删除的方法。
ArrayList<Integer> list = new ArrayList<Integer>(); list.add(1); for (Integer integer : list) { list.remove(integer); }发生并发修改异常,这是因为在迭代器内部维护索引位置信息,在迭代的过程中是不能让list容器发生变化,否则索引就失效了。 Exception in thread “main” java.util.ConcurrentModificationException
如果要避免这种异常,使用迭代器自己的remove删除方法
List<Integer> list = new ArrayList<Integer>(); list.add(22); Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()){ if (iterator.next() <=100){ iterator.remove(); }下一篇迭代器原理