Java集合实现(一) ArrayList源码以及手写ArrayList

一、ArrayList集合介绍

简单来说,它就是一个动态数组

普通的数组一旦长度确认,长度就不再能改变。

而该ArrayList不一样,长度可变,就是一个动态大小的数组。

【底层代码】

Java集合实现(一) ArrayList源码以及手写ArrayList_第1张图片

 【继承关系】

Java集合实现(一) ArrayList源码以及手写ArrayList_第2张图片 二、主要方法实现原理

1、add方法

  • public boolean add(E e) :数组末尾直接添加元素
  • public void add(int index, E element) :指定下标位置添加元素

Java集合实现(一) ArrayList源码以及手写ArrayList_第3张图片

 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、删除指定位置元素

删除指定下标位置元素,删除位置以后元素依次向前移动一个位置

Java集合实现(一) ArrayList源码以及手写ArrayList_第4张图片

删除结果,可以访问的区域减一,末尾区域记得置为空,才可以被垃圾回收。 

Java集合实现(一) ArrayList源码以及手写ArrayList_第5张图片

 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个一定会越界,此时必须进行扩容。

Java集合实现(一) ArrayList源码以及手写ArrayList_第6张图片

 下面是ArrayList底层扩容,官方是进行1.5倍大小的扩容(目的是既申请了一些空间,又不会申请太多,浪费空间,即最佳实践的结果)

Java集合实现(一) ArrayList源码以及手写ArrayList_第7张图片

 笔者实现的简单扩容代码:

    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、实现迭代器接口,暴露数组遍历功能

Java集合实现(一) ArrayList源码以及手写ArrayList_第8张图片

 【自实现代码】:

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底层有很多奥秘,比如深克隆浅客隆问题、序列化等等,加油努力探索吧!!

完结撒花……

你可能感兴趣的:(手写源码,java,jvm,数据结构)