java中ArrayList的实现原理:
ArrayList的底层是通过数组实现的,即ArrayList对象中维护着一个数组对象,如下:
private static final int DEFAULT_CAPACITY = 10; //默认的数组容量
transient Object[] elementData; //实际存储数据的数组容器
public ArrayList() { //默认构造方法
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //由此可以知道ArrayList的最大长度是Integer.MAX_VALUE
由于数组声明长度后不可更改,那么ArrayList是如何实现add功能的呢?
源码如下:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
其中ensureCapacityInternal方法实际上就是为数组扩容如下:
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);
}
扩容的思想:就是什么一个新的长度更大的数组,然后将之前数组中的元素复制到该数组中。
这样数据就有了存储的地方,最后需要解决的一个问题就是 迭代器模式
首先ArrayList的父子关系如下图所示:
此图来自百度百科里面的集合总父子关系:现在只需要关注 Iterable Iterator ListIterator Collection List AbstractCollection AbstractList ArrayList这几个类
在逐个解析这些类之前,有必要先温习一下迭代器模式:
虽然JDK中的迭代器模型比上述模型要复杂好多,但是目的都是一样的。简单的理解了上述模型之后,再来看上述的类
Iterable 接口 定义如下:
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
里面最重要的抽象方法为 iterator() 实质就是返回一个迭代器
实现了该接口的类就能够使用增强for循环了。
再来看Collection 接口的定义:
public interface Collection<E> extends Iterable<E>
也就是这样 所有Collection接口的实现类都可以使用增强for循环。
然后就是 iterator 接口:
public interface Iterator<E> {
boolean hasNext(); //是否有下一个元素
E next(); //获取下一个元素
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
该接口自定义了迭代器需要的最基本的也最重要的方法 hasNext() next() 实现了这两个方法的迭代器就基本可以用了,但是JDK为了增强ArrayList的特性,为ArrayList又定义了一个迭代器 ListIterator
定义如下:
public interface ListIterator<E> extends Iterator<E> {
boolean hasNext();
E next();
boolean hasPrevious();
E previous();
int nextIndex();
int previousIndex();
void remove();
void set(E e);
void add(E e);
}
可以看到ListIterator继承自Iterator,同时对Iterator做了扩展
下面再来看AbstractCollection
public abstract class AbstractCollection<E> implements Collection<E> {
protected AbstractCollection() {
}
public abstract Iterator<E> iterator();
}
里面其它的一些实现方法都比较简单,同时也不是很重要,里面最重要的一个方法就是 iterator()方法,该方法是获取迭代器的方法。
再来看List
public interface List<E> extends Collection<E> {
Iterator<E> iterator();
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
}
该接口中其它的接口都被我删掉了,我们只看重要的部分
1.该接口继承自Collection接口
2.从该接口中可以获取 两种类型的迭代器 a.基类迭代器 Iterator b.增强类型的迭代器 Listiterator
再来看看AbstractList
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
protected AbstractList() {
}
public Iterator<E> iterator() {
return new Itr();
}
public ListIterator<E> listIterator() {
return listIterator(0);
}
public ListIterator<E> listIterator(final int index) {
return new ListItr(index);
}
private class Itr implements Iterator<E> {
}
private class ListItr extends Itr implements ListIterator<E> {
}
}
class SubList<E> extends AbstractList<E> {
}
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
}
里面值得关注的地方就在于该抽象类中包含了两个私有内部类 Itr 和 ListItr 分别实现 Iterator 和ListIterator 。以供为该抽象类的 iterator(),listIterator()方法提供返回值。
另外比较有趣的是,这个类文件中包含了3个类定义,是比较少见的一种写法,实际上一个类文件中有多个类时只要保证只有一个public 的类,并且该类的名称了文件名相同,即可。
最后需要看的就是 ArrayList对象了
定义如下:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
该类就并没有什么特别值得关注的地方了,仅仅是实现了,而实现的思想就是使用数组作为元素的存储了。
另外我们再来关注一下,ArrayList里面维护的两个内部类:
Itr 和 ListItr
private class Itr implements Iterator<E> {
int cursor;
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
public E next() {
int i = cursor;
Object[] elementData = ArrayList.this.elementData;
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
}
}
可见 Itr中维护着ArrayList中的存储数据的elementData数组对象,维护的目的就是为了对Iterator接口中的方法进行实现。
ListItr 当然也是一样。