数据结构
ArrayList的底层数据结构就是一个数组,数组元素的类型为Object类型,对ArrayList的所有操作底层都是基于数组的。
安全性
对ArrayList进行添加元素的操作的时候是分两个步骤进行的,即: 第一步先在object[size]的位置上存放需要添加的元素; 第二步将size的值增加1。 由于这个过程在多线程的环境下是不能保证具有原子性的,因此ArrayList在多线程的环境下是线程不安全的。 具体举例说明: 在单线程运行的情况下,如果Size = 0,添加一个元素后,此元素在位置 0,而且Size=1;而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增 加 Size 的值。 那好,现在我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而Size却等于 2。这就是“线程不安全”了。 如果非要在多线程的环境下使用ArrayList,就需要保证它的线程安全性,通常有两种解决办法: 第一,使用synchronized关键字; 第二,可以用Collections类中的静态方法synchronizedList();对ArrayList进行调用即可。
继承和实现的类
ArrayList继承AbstractList抽象父类; 实现的接口: 1、List接口(规定了List的操作规范) 2、RandomAccess(可随机访问) 3、Cloneable(可拷贝) 4、Serializable(可序列化)
主要成员变量
public class ArrayList < E> extends AbstractList < E>
implements List < E> , RandomAccess, Cloneable, java. io. Serializable
{
private static final long serialVersionUID = 8683452581122892189 L;
private static final int DEFAULT_CAPACITY = 10 ;
private static final Object[ ] EMPTY_ELEMENTDATA = { } ;
private static final Object[ ] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = { } ;
transient Object[ ] elementData;
private int size;
private static final int MAX_ARRAY_SIZE = Integer. MAX_VALUE - 8 ;
protected transient int modCount = 0 ;
}
add()方法
public boolean add ( E e) {
ensureCapacityInternal ( size + 1 ) ;
elementData[ size++ ] = e;
return true ;
}
扩容机制
private void ensureCapacityInternal ( int minCapacity) {
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;
int newCapacity = oldCapacity + ( oldCapacity >> 1 ) ;
if ( newCapacity - minCapacity < 0 )
newCapacity = minCapacity;
if ( newCapacity - MAX_ARRAY_SIZE > 0 )
newCapacity = hugeCapacity ( minCapacity) ;
elementData = Arrays. copyOf ( elementData, newCapacity) ;
}
private static int hugeCapacity ( int minCapacity) {
if ( minCapacity < 0 )
throw new OutOfMemoryError ( ) ;
return ( minCapacity > MAX_ARRAY_SIZE) ?
Integer. MAX_VALUE :
MAX_ARRAY_SIZE;
}
set()方法
public E set ( int index, E element) {
rangeCheck ( index) ;
E oldValue = elementData ( index) ;
elementData[ index] = element;
return oldValue;
}
private void rangeCheck ( int index) {
if ( index >= size)
throw new IndexOutOfBoundsException ( outOfBoundsMsg ( index) ) ;
}
@SuppressWarnings ( "unchecked" )
E elementData ( int index) {
return ( E) elementData[ index] ;
}
remove()方法
public E remove ( int index) {
rangeCheck ( index) ;
modCount++ ;
E oldValue = elementData ( index) ;
int numMoved = size - index - 1 ;
if ( numMoved > 0 )
System. arraycopy ( elementData, index+ 1 , elementData, index,
numMoved) ;
elementData[ -- size] = null;
return oldValue;
}
get()方法
public E get ( int index) {
rangeCheck ( index) ;
return elementData ( index) ;
}
indexOf()方法
public int indexOf ( Object o) {
if ( o == null) {
for ( int i = 0 ; i < size; i++ )
if ( elementData[ i] == null)
return i;
} else {
for ( int i = 0 ; i < size; i++ )
if ( o. equals ( elementData[ i] ) )
return i;
}
return - 1 ;
}
ArrayList的优点
ArrayList底层以数组实现,是一种随机访问模式,因此查找也就是get的时候非常快。 ArrayList在顺序添加一个元素的时候非常方便,只是往数组里面添加了一个元素而已。 根据下标遍历元素,效率高。 根据下标访问元素,效率高。 可以自动扩容,默认为每次扩容为原来的1.5倍。
ArrayList的缺点
插入和删除元素的效率不高。 根据元素值查找元素下标需要遍历整个元素数组,效率不高。 线程不安全。