介绍
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();
}
下一篇迭代器原理