ArrayList,
分享于 点击 27066 次 点评:211
ArrayList,
一、类名public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
List 接口:定义了对list集合操作的方法。
AbstactList:提供了对List接口的默认实现RandomAccess:是一个标记接口,接口内没有定义任何内容。 Cloneable接口:可以调用Object.clone方法返回该对象的浅拷贝。 Serializable 接口:以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。序列化接口没有方法或字段,仅用于标识可序列化的语义。
二、类属性
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;//用来记录数组大小
三、构造方法
1、参数为int型,创建一个指定大小的集合,如果传入的参数等于0,则将EMPTY_ELEMENTDATA赋值给elementData。
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
2、无参构造函数,elementData初始化为大小为0的数组。 public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
3、参数为一个集合。将传入的集合转成数组赋值给elementData。/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
三、方法。
1、add(E e):ArrayList底层实现是一个数组,在执行添加方法时,需要判断数组下标是否越界了。通过ensureCapacityInternal方法来检查数组大小,如果越界,则返回一个新的数组。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
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++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
2、add(int index,E element):在集合的某个位置插入数据,在插入数据之前首先要保证,数组没有越界。 arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src:原始数组,srcPos:从原始数组什么位置开始复制,dest:目标数组,destPos:目标数组的起始位置,lngth:复制长度
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
3、addAll(Collection c):添加一个集合。将传入的集合转换成数组,根据转换后的数组大小和原来集合的大小重新拓展集合大小,再通过arraycopy方法将转换后的数组复制到集合的末尾,最后调整size大小。
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
4、addAll(int index,Collection c)方法:跟addAll(Collection c)方法差不多,区别是:如果集合的实际大小(size)大于index,则在index处插入被传入的集合值,原来的值向后移动numNew个位置(被传入的集合大小)
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
5、clear 方法:循环将elementData的值置为null,在将size 的大小设为0。但是elementData数组的长度并没有缩小。
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
6、clone方法:调用父类的clone()返回一个对象副本,再将原来集合的内容赋值到该副本。modCount值为0。
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
7、contains()方法:contains方法直接调用indexOf方法。indexOf方法中循环elementData数组,通过equals方法来判断是否存在与传入进来的对象相等的值,如果有则返回该值在数组中的下标,然后在contains方法中判断如果大于等于0则返回true.
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
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;
}
8、get方法:首先检查是否越界,然后直接返回数组的值。
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
E elementData(int index) {
return (E) elementData[index];
}
9、isEmpty:直接返回size。
public boolean isEmpty() {
return size == 0;
}
10、remove(int index)方法:先判断是否越界,然后取出index处的值留作为返回结果,再通过arraycopy 方法将elementData在index后面的值往前移一位,最后将size处的值置为空,size减1。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; // clear to let GC do its work
return oldValue;
}
11、remove(Object o):直接遍历elementData方法,判断数组中是否存在与传入的对象相等的值,如果存在,则删除,并返回true。
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
12、toArray方法
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
13、trimToSize():将elementData的长度设置为size。
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
相关文章
- 暂无相关文章
用户点评