简单来说,它就是一个动态数组
普通的数组一旦长度确认,长度就不再能改变。
而该ArrayList不一样,长度可变,就是一个动态大小的数组。
【底层代码】
【继承关系】
1、add方法
public boolean add(E e)实现:这里的扩容后面再说明
public boolean add(E e) {
ensureCapacity(); //扩容
this.elementData[size++] = e;
return true;
}
public void add(int index, E element)实现:
public void add(int index, E element) {
if (index < 0 || index >= this.size) {
throw new ArrayIndexOutOfBoundsException(outOfBoundsMsg(index));
}
//插入位置以后元素依次向后移动一个位置
for (int i = size; i > index; i--) {
this.elementData[i] = this.elementData[i - 1];
}
this.elementData[index] = element;
}
2、删除指定位置元素
删除指定下标位置元素,删除位置以后元素依次向前移动一个位置
删除结果,可以访问的区域减一,末尾区域记得置为空,才可以被垃圾回收。
public E remove(int index)实现
public E remove(int index) {
if (index < 0 || index >= this.size) {
throw new ArrayIndexOutOfBoundsException(outOfBoundsMsg(index));
}
E deleteValue = elementData(index);
//删除位置以后元素依次向前移动一个位置
for (int i = index; i < size; i++) {
this.elementData[i] = this.elementData[i + 1];
}
this.elementData[--size] = null;
return deleteValue;
}
3、ArrayList的扩容机制
看看ArrayList底层代码,如果没有设置大小,默认大小为10。所以只要不断插入数据,超过10个一定会越界,此时必须进行扩容。
下面是ArrayList底层扩容,官方是进行1.5倍大小的扩容(目的是既申请了一些空间,又不会申请太多,浪费空间,即最佳实践的结果)
笔者实现的简单扩容代码:
public void ensureCapacity() {
if (size < this.elementData.length) {
return;
}
int newSize = elementData.length + (elementData.length >> 1); //原来数组大小的1.5倍
if (newSize < 0) {
throw new OutOfMemoryError();
}
elementData = Arrays.copyOf(elementData, newSize);
}
4、实现迭代器接口,暴露数组遍历功能
【自实现代码】:
public class ArrayList implements Iterable {
@Override
public Iterator iterator() {
return new ArrayListIterator();
}
private class ArrayListIterator implements Iterator {
int currIndex = 0;
@Override
public boolean hasNext() {
return currIndex != size;
}
@Override
public E next() {
return elementData(currIndex++);
}
}
}
5、完整实现代码
public class ArrayList implements Iterable {
private static final int DEFAULT_CAPACITY = 10;
private Object[] elementData;
private int size;
public ArrayList() {
this.elementData = new Object[DEFAULT_CAPACITY];
}
private String outOfBoundsMsg(int index) {
return "Index: " + index + ", Size: " + this.size;
}
private void rangeCheck(int index) {
if (index < 0 || index >= this.size) {
throw new ArrayIndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
public void ensureCapacity() {
if (size < this.elementData.length) {
return;
}
int newSize = elementData.length + (elementData.length >> 1); //原来数组大小的1.5倍
if (newSize < 0) {
throw new OutOfMemoryError();
}
elementData = Arrays.copyOf(elementData, newSize);
}
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
private E elementData(int index) {
return (E) elementData[index];
}
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
this.elementData[index] = element;
return oldValue;
}
public boolean add(E e) {
ensureCapacity(); //扩容
this.elementData[size++] = e;
return true;
}
public void add(int index, E element) {
rangeCheck(index);
//插入位置以后元素依次向后移动一个位置
for (int i = size; i > index; i--) {
this.elementData[i] = this.elementData[i - 1];
}
this.elementData[index] = element;
}
public E remove(int index) {
rangeCheck(index);
E deleteValue = elementData(index);
//删除位置以后元素依次向前移动一个位置
for (int i = index; i < size; i++) {
this.elementData[i] = this.elementData[i + 1];
}
this.elementData[--size] = null;
return deleteValue;
}
public void clear() {
Arrays.fill(this.elementData, null);
this.size = 0;
}
public int size() {
return this.size;
}
public boolean isEmpty() {
return this.size == 0;
}
@Override
public Iterator iterator() {
return new ArrayListIterator();
}
private class ArrayListIterator implements Iterator {
int currIndex = 0;
@Override
public boolean hasNext() {
return currIndex != size;
}
@Override
public E next() {
return elementData(currIndex++);
}
}
}
public class ArrayListTest {
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
list.add(i);
}
list.remove(11);
list.set(18,20);
list.add(21);
for (Integer integer : list) {
System.out.print(integer+" ");
}
System.out.println();
list.clear();
System.out.println(list.size());
}
}
【测试结果】
总之,ArrayList底层有很多奥秘,比如深克隆浅客隆问题、序列化等等,加油努力探索吧!!
完结撒花……