JAVA中ArrayList的实现与分析

ArrayList 单链表

  • 是一种可增长的数组实现
  • 优点在于,对get和set的调用花费常数时间
  • 缺点是add和remove的代价昂贵
实现
package com.leeyf.myarraylist;

import java.util.Iterator;

public abstract class MyArrayList<T> implements Iterable<T> {
    //初始化容器容量
    private static final int DEFAULT_CAPACITY = 10;
    //当前项数
    private int theSize;
    //基础数组
    private T[] theItems;

    public MyArrayList() {
        doClear();
    }

    //清空链表
    public void clear() {
        doClear();
    }

    private void doClear() {
        theSize = 0;
        ensureCapacity(DEFAULT_CAPACITY);
    }

    //返回当前项数
    public int size() {
        return theSize;
    }

    public boolean isEmpty() {
        return theSize == 0;
    }

    //缩减容器大小
    public void trimToSize() {
        ensureCapacity(size());
    }

    public T get(int index) {
        if (index < 0 || index >= size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        return theItems[index];
    }

    public T set(int index, T newVal) {
        if (index < 0 || index >= size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        T old = theItems[index];
        theItems[index] = newVal;
        return old;
    }

    public void ensureCapacity(int newCapacity) {
        //如果新设置的大小比当前容器大小小,则不执行
        if (newCapacity < size()) {
            return;
        }

        T[] old = theItems;
        theItems = (T[]) new Object[newCapacity]; //泛型数组的创建是非法的.这里创建一个泛型类型界限的数组,然后使用一个数组进行类型转换来实现.
        for (int i = 0; i < size(); i++) {
            theItems[i] = old[i];
        }
    }

    public boolean add(T x) {

        add(size(), x);
        return true;
    }

    public void add(int index, T x) {
        //如果链表已满,则扩容
        if (theItems.length == size()) {
            ensureCapacity(size() * 2 + 1);
        }
        //从最后一项开始到index,后移一位
        for (int i = theSize; i > index; i--) {
            theItems[i] = theItems[i - 1];
        }
        theItems[index] = x;
        theSize++;
    }

    public T remove(int index) {
        T removeItem = theItems[index];
        //从index到最后一项,前移一位
        for (int i = index; i < size() - 1; i++) {
            theItems[i] = theItems[i + 1];
        }
        theSize--;
        return removeItem;
    }

    public java.util.Iterator<T> iterator() {
        return new ArrayListIterator();
    }


    private class ArrayListIterator implements java.util.Iterator<T> {
        private int current = 0;

        public boolean hasNext() {
            return current < size();
        }

        public T next() {
            if (!hasNext()) {
                throw new java.util.NoSuchElementException();
            }
            return theItems[current++];
        }

        public void remove() {
            MyArrayList.this.remove(--current);
        }
    }

}

分析
  • ensureCapacity是对容器大小的调整,既可以用来容器扩容,也可做收缩基础数组,只不过当指定容器至少和原大小一样时才适用.

  • 第64行中,因为泛型数组的创建是非法的,所以我们用一个数组来类型转换

  • 两个add方法,第一个add是添加到表的末端的并通过调用来添加到指定位置的.第二个则是添加到指定位置.

  • removeadd相似,只是在指定位置后的元素,前移一位.

  • ArrayListIterator内部类则是对Iterator接口的实现类.ArrayListIterator存储当前位置的概念,并提供了hasNext,nextremove的实现.

    • 当前位置表示要被查看的下一元素的数组下标,所以初始值为0\
迭代器、JAVA嵌套类和内部类

ArrayListIterator作为一个内部类是如何工作的

未完待续。。。

全部评论

相关推荐

10-30 23:23
已编辑
中山大学 Web前端
去B座二楼砸水泥地:这无论是个人素质还是专业素质都👇拉满了吧
点赞 评论 收藏
分享
我即大橘:耐泡王
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务