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

一、ArrayList集合介绍

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

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

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

【底层代码】

 【继承关系】

 二、主要方法实现原理

1、add方法

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

 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<E> implements Iterable<E> {   
 @Override
    public Iterator<E> iterator() {
        return new ArrayListIterator();
    }

    private class ArrayListIterator implements Iterator<E> {

        int currIndex = 0;

        @Override
        public boolean hasNext() {
            return currIndex != size;
        }

        @Override
        public E next() {
            return elementData(currIndex++);
        }
    }
}

 5、完整实现代码

public class ArrayList<E> implements Iterable<E> {

    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<E> iterator() {
        return new ArrayListIterator();
    }

    private class ArrayListIterator implements Iterator<E> {

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

完结撒花……

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫蜜柚子茶

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值