java集合框架_List_ArrayList

1.ArrayList的特点

  • 内部是通过数组实现的,
  • 支持随机访问
  • 数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中。
  • 当从 ArrayList 的中间位置插入或者删除元素时,需要对数组进 行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。
  • 线程不安全
  • 容量不够时

2.ArrayList构造函数

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
	private static final long serialVersionUID = 8683452581122892189L;
    private static final int DEFAULT_CAPACITY = 10;
    private static final Object[] EMPTY_ELEMENTDATA = {};
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    transient Object[] elementData;//用数组来村南方各种存放数据,elementData.length 可以存放的元素个数
    private int size;//实中元素的少数

2.1 public ArrayList()

/**
     * Constructs an empty list with an initial capacity of ten.
     * 初始值为10 如果,new ArrayList()没有赋值时默认长度为10
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

2.2 public ArrayList(int initialCapacity)

 public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];//如果指定new ArrayList(len)的初始长度大于0.则直接生成这个长度的object数组
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;//如果初始为0则为空{}
        } else {//如果指定的初始容量长度<0,则抛出数字不合法异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

2.3public ArrayList(Collection<? extends E> c)

  • 按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表
  • 如果集合长度为0则为{}

3.ArrayList常用方法

3.1 add()

private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)//如果插入元素此时的list的元素个数等于了数组的长度,则进行扩容操作
            elementData = grow();//扩容
        elementData[s] = e;//并把元素增加到最后一个元素后面
        size = s + 1;
    }
    public boolean add(E e) {
        modCount++;//modCount记录操作次数
        add(e, elementData, size);
        return true;
    }

    public void add(int index, E element) {//表示在第几个位置插入元素
        rangeCheckForAdd(index);//如果插入的位置>size||<0则抛出异常
        modCount++;
        final int s;
        Object[] elementData;
        if ((s = size) == (elementData = this.elementData).length)//如果要插入的元素刚好等于容易可以容纳的长度 则进行扩容
            elementData = grow();
        System.arraycopy(elementData, index,
                         elementData, index + 1,
                         s - index);//这个native了,大概意思可能是让原来的ArrayList的index前半部分,index后半部分装在新的扩容的数组里面,index位置有一个空位置,留给e
        elementData[index] = element;
        size = s + 1;
    }

3.2 那来谈谈扩容吧 grow()

 public void ensureCapacity(int minCapacity) {
        if (minCapacity > elementData.length
            && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
                 && minCapacity <= DEFAULT_CAPACITY)) {
            modCount++;
            grow(minCapacity);
        }
    }
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

  
    private Object[] grow(int minCapacity) {
        return elementData = Arrays.copyOf(elementData,
                                           newCapacity(minCapacity));
    }

    private Object[] grow() {
        return grow(size + 1);
    }

    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容 后容量为现在的1.5倍
        if (newCapacity - minCapacity <= 0) {//如果扩容之后的容量还不满足所需要的最小容量
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)//第一
                return Math.max(DEFAULT_CAPACITY, minCapacity);
            if (minCapacity < 0) // overflow
                throw new OutOfMemoryError();
            return minCapacity;
        }
        return (newCapacity - MAX_ARRAY_SIZE <= 0)//如果扩容后的容量比最大容量大,则
            ? newCapacity
            : hugeCapacity(minCapacity);
    }
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE)//如果扩容1.5倍之后太大则,
            ? Integer.MAX_VALUE
            : MAX_ARRAY_SIZE;
    }

3.3 public E remove(int index)

 public E remove(int index) {
        Objects.checkIndex(index, size);//查看要remmove的元素的下标是否符合要求
        final Object[] es = elementData;

        @SuppressWarnings("unchecked") E oldValue = (E) es[index];
        fastRemove(es, index);

        return oldValue;
    }

 public boolean remove(Object o) {//判断是否可以remove
        final Object[] es = elementData;
        final int size = this.size;
        int i = 0;
        found: {
            if (o == null) {
                for (; i < size; i++)
                    if (es[i] == null)
                        break found;
            } else {
                for (; i < size; i++)
                    if (o.equals(es[i]))
                        break found;
            }
            return false;
        }
        fastRemove(es, i);
        return true;
    }
    private void fastRemove(Object[] es, int i) {
        modCount++;
        final int newSize;
        if ((newSize = size - 1) > i)//如果为true说明要删除的不是最后一个元素,而是中间的位置元素
            System.arraycopy(es, i + 1, es, i, newSize - i);//把index+1的后面所有元素向前移动一位
            //es:原元素集合
            //i + 1 开始的位置
            //es复制到的目标元素
            //i 目标元素的开始位置
           //newSize - i 以及复制的长度
        es[size = newSize] = null;//把之前最后一个元素1的位置值为null,
    }

3.4 get set

  • 因为底层使用数组来实现,所以 底层直接通过[index]的方式获取和设置值,这里不阐述

3.5 equals

public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (!(o instanceof List)) {
            return false;
        }
        final int expectedModCount = modCount;//mpdCount对ArrayList的操作
        boolean equal = (o.getClass() == ArrayList.class)
            ? equalsArrayList((ArrayList<?>) o)
            : equalsRange((List<?>) o, 0, size);

        checkForComodification(expectedModCount);
        return equal;
    }

    boolean equalsRange(List<?> other, int from, int to) {
        final Object[] es = elementData;
        if (to > es.length) {
            throw new ConcurrentModificationException();
        }
        var oit = other.iterator();
        for (; from < to; from++) {
            if (!oit.hasNext() || !Objects.equals(es[from], oit.next())) {
                return false;
            }
        }
        return !oit.hasNext();
    }

    private boolean equalsArrayList(ArrayList<?> other) {
        final int otherModCount = other.modCount;
        final int s = size;
        boolean equal;
        if (equal = (s == other.size)) {
            final Object[] otherEs = other.elementData;
            final Object[] es = elementData;
            if (s > es.length || s > otherEs.length) {
                throw new ConcurrentModificationException();
            }
            for (int i = 0; i < s; i++) {
                if (!Objects.equals(es[i], otherEs[i])) {
                    equal = false;
                    break;
                }
            }
        }
        other.checkForComodification(otherModCount);
        return equal;
    }

如果两个地址相同返回true,入托不属于List的一个实例则直接返回false

如果输入类型ArrayList

如果size一样且a.equals(b) a.size的长度不大于b的size,&& 对比每一个元素,如果符合,他们的操作次数,如果都符合则true,有一个不满足都抱错或者false

如果输入的类型为list

调用equalsRange方法 使用迭代器 一一对比

3.6 public ListIterator<E> listIterator(int index)

private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        // prevent creating a synthetic constructor
        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
  • hasNext 实现比较简单,如果下一个元素的下标等于集合的大小 ,就证明到最后了。

  • next 方法也不复杂,但很关键。首先判断 expectedModCount 和 modCount是否相等。然后对 cursor进行判断,看是否超过集合大小和数组长度。然后将cursor 赋值给lastRet ,并返回下标为 lastRet 的元素。最后将 cursor自增 1。开始时,cursor = 0,lastRet = -1;每调用一次 next 方法, cursor 和 lastRet 都会自增 1。

  • remove 方法首先会判断 lastRet的值是否小于 0,然后在检查expectedModCountmodCount是否相等。接下来是关键,直接调用 ArrayListremove方法删除下标为 lastRet 的元素。然后将 lastRet赋值给cursor,将lastRet重新赋值为 -1,并将 modCount重新赋值给expectedModCount

4.最后总结特点

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值