Java集合框架分析(二)——List集合之ArrayList源码分析

            Java集合框架分析(二)——List集合之ArrayList源码分析

    因为复习集合框架的本意是要学习集合框架,因此我接下来做三个任务,分析源码,自己实现对应的数据结构,实现下集合中的大部分常用方法。

    上一章说到List的特点:元素是有序的并且元素是可以重复的,因为该集合有索引,讲到这里学过数据结构的人就知道了其实这就是一个线性表,确实list的底层数据结构就是线性表。

我们来看List接口的实现类,最常见的大概就四种,ArrayList,  LinkedList,  Vector,  Stack.,这里我们就对ArrayList和LinkedList进行分析因为他们是最常用的并且代表了线性表的两个典型实现,顺序表(数组)和链表。

  首先是ArrayList,它的底层数据结构就是数组,因为每个元素有索引,所以他的特点是:查询快,但是增删慢,而且线程不同步(多线程还没有深入学习,这里不做分析)。

好了我们就从源码开始分析。

首先看ArrayList的构造函数

 

//默认的构造函数
public ArrayList() {
this(10);
}
//initialCapacity是指默认的容量,也就是数组容量大小
public ArrayList(int initialCapacity) {
super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
this.elementData = new Object[initialCapacity];
}
//创建一个包含Collection的ArrayList
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
if (elementData.getClass() != Object[].class)
    elementData = Arrays.copyOf(elementData, size, Object[].class);
    }

 

上我们可以知道其实ArrayList其实就是一个动态数组,当数据超出容量时会自动扩容,从默认的构造函数可以知道他的起始默认长度是10.其中elementDatasize是关键,我们看看elementData的定义:

Object[] elementData 显然她是一个Object类型的动态数组,用来保存元素,他的容量会根据具体的元素大小而动态的增长。

而size从上可以看到 size = elementData.length,其实就是动态数组的实际大小。

接下来把源码贴上来,其中已经加上了我的注释:

 

package com.code;
 
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.LinkedList;
import java.util.List;
import java.util.RandomAccess;
import java.util.Vector;
 
public class ArrayList<E> extends AbstractList<E> implements List<E>,
RandomAccess, Cloneable, java.io.Serializable {
// 版本序列号
private static final long serialVersionUID = 8683452581122892189L;
 
// 保存元素的动态数组
private transient Object[] elementData;
 
// 动态数组的实际大小
private int size;
 
// 带容量大小的构造函数
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "
+ initialCapacity);
this.elementData = new Object[initialCapacity];
}
 
// 默认的构造函数,默认大小是10
public ArrayList() {
this(10);
}
 
// 创建一个包含collection的ArrayList
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
 
// 将当前的数组容量设置为实际元素的个数
public void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (size < oldCapacity) {
elementData = Arrays.copyOf(elementData, size);
}
}
 
// 动态数组扩容的方法,关键!这是和Vector的区别之一,算法是新的数组容量=(旧的数组容量*3)/2+1
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3) / 2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
 
// 返回元素的实际个数也就是ArrayList的实际大小
public int size() {
return size;
}
 
// 实现的Collection的方法,判断是否为空
public boolean isEmpty() {
return size == 0;
}
 
// 看是否包含一个对象,调用的是indexOf方法
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;
}
 
// 这是反向查找,具体什么作用未知
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size - 1; i >= 0; i--)
if (elementData[i] == null)
return i;
} else {
for (int i = size - 1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
 
// 克隆函数
public Object clone() {
try {
ArrayList<E> v = (ArrayList<E>) super.clone();
// 将当前元素复制到v中
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();
}
}
 
// 返回ArrayList的Object数组
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
 
//
public <T> T[] toArray(T[] a) {
// 如果数组a的个数小于ArrayList的实际元素个数
if (a.length < size)
// 创建一个新的数组
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
// 将a的元素复制到新的数组中
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
 
// Positional Access Operations
// 根据索引值获取对应的元素
public E get(int index) {
RangeCheck(index);
 
return (E) elementData[index];
}
 
// 修改索引位置的元素的值
public E set(int index, E element) {
RangeCheck(index);
 
E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}
 
// 添加一个元素到数组的末尾,实现原理是数组的长度加1
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
 
// 根据索引来添加指定元素
public void add(int index, E element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ size);
 
ensureCapacity(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1, size
- index);
elementData[index] = element;
size++;
}
 
// 根据索引值来移除指定的元素,,返回的是移除的值
public E remove(int index) {
RangeCheck(index);
 
modCount++;
E oldValue = (E) elementData[index];
 
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index + 1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
 
return oldValue;
}
 
// 删除ArrayList中的指定元素
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;
}
 
// 快速删除指定索引的元素,和remove方法相比少了RangeCheck(index);这个步骤
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; // Let gc do its work
}
 
// 清空所有元素,就是遍历元素把所有元素变成null
public void clear() {
modCount++;
 
// Let gc do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
 
size = 0;
}
 
// 将集合c加到ArrayList中
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
 
// 添加集合c到指定索引位置
public boolean addAll(int index, Collection<? extends E> c) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ size);
 
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(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;
}
 
// 删除fromIndex到toIndex之间的所有元素
protected void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = size - toIndex;
System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved);
 
// Let gc do its work
int newSize = size - (toIndex - fromIndex);
while (size != newSize)
elementData[--size] = null;
}
 
private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ size);
}
 
// 将ArrayList的“容量,所有的元素值”都写入到输出流中
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
 
// Write out array length
s.writeInt(elementData.length);
 
// Write out all elements in the proper order.
for (int i = 0; i < size; i++)
s.writeObject(elementData[i]);
 
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
 
}
 
// 先将ArrayList的“容量”读出,然后将“所有的元素值”读出
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in size, and any hidden stuff
s.defaultReadObject();
 
// Read in array length and allocate array
int arrayLength = s.readInt();
Object[] a = elementData = new Object[arrayLength];
 
// Read in all elements in the proper order.
for (int i = 0; i < size; i++)
a[i] = s.readObject();
}
}

 

 

总的来说

(1)ArrayList就是一个动态数组的实现类。容量不足的时候会设置新的容量。新容量=(旧的容量*3)/2+1

(2)源码的最后部分是对io的写入和读取

 

好了先分析到这里,妈蛋这个点了明天,不对应该是今天还满课,明天还要考线代。。。

 

 

猜你喜欢

转载自linhaoxiang.iteye.com/blog/2056433