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

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(elementDatasize, 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(elementDatasize, Object[].class);

}

 

// 将当前的数组容量设置为实际元素的个数

public void trimToSize() {

modCount++;

int oldCapacity = elementData.length;

if (size < oldCapacity) {

elementData = Arrays.copyOf(elementDatasize);

}

}

 

// 动态数组扩容的方法,关键!这是和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(elementDatasize);

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(elementDatasize);

}

 

//

public <T> T[] toArray(T[] a) {

// 如果数组a的个数小于ArrayList的实际元素个数

if (a.length < size)

// 创建一个新的数组

return (T[]) Arrays.copyOf(elementDatasize, 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, elementDatasize, 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的写入和读取

 

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