ArrayList和LindekList-学习

1.ArrayList存储结构

数组(数组是采用一段连续的存储单元来存储数据)
特点,查询快O(1)。删除插入慢(O(N))

数组查找遵循下面公式
数组 a[n] = 起始位置+(n*字节数);

2.ArrayList代码实现

在这里插入图片描述

2.1 首先看类的继承,实现关系。

继承了AbstractList,实现了List,RandomAccess, Cloneable,java.io.Serializable。

1. List ???(比较奇怪,AbstractList里面也实现了这个接口,这里又继承了,很奇怪。不知道为啥)
2. RandomAccess随机访问(get方法)
3. Cloneable 拷贝
4. Serializable序列化

2.2 基本属性

1.  int DEFAULT_CAPACITY = 10; 数组初始化大小
2. Object[] EMPTY_ELEMENTDATA = {} ;空数组  用于有参构造创建数组。代码中能估算出list放多少数据,可以直接指定长度,优化速度。
3.  Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};空数组 用于无参构造,就是一个空数组。
4.  transient Object[] elementData;  arrayList真正存放元素的地方,长度大于等于size
5. size 数组长度

2.3.构造方法

/**
     * Constructs an empty list with the specified initial capacity.
     *
     * @param  initialCapacity  the initial capacity of the list
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    // 当 initialCapacity 为零时则是把 EMPTY_ELEMENTDATA 赋值给 elementData。
    // 当 initialCapacity 大于零时初始化一个大小为 initialCapacity 的 object 数组并赋值给 elementData。
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    //无参构造器,构造一个容量大小为 10 的空的 list 集合,但构造函数只是给 elementData 赋值了一个空的数组,其实是在第一次添加元素时容量扩大至 10 的。
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
     //将 Collection 转化为数组,数组长度赋值给 size。 
     //如果 size 不为零,则判断 elementData 的 class 类型是否为 ArrayList,不是的话则做一次转换。 
     //如果 size 为零,则把 EMPTY_ELEMENTDATA 赋值给 elementData,相当于new ArrayList(0)。
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

2.4 常用的方法

  1. 1.add
/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
   //直接尾部添加元素。
public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

//指定下标添加元素
  public void add(int index, E element) {
        //下标越界检查
        rangeCheckForAdd(index);
        //容量检查
        ensureCapacityInternal(size + 1);  

         //依次复制插入位置及后面的数组元素,到后面一格。
         //因此复制完后,添加的下标位置和下一个位置指向对同一个对象
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
         //再将元素赋值给该下标
        elementData[index] = element;
        size++;
    }
  

3.1 ensureCapacityInternal里面有个扩容的操作
private void grow(int minCapacity) {
        //获取当前数组长度
        int oldCapacity = elementData.length;
       
        //默认将扩容至原来容量的 1.5 倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        
        //如果1.5倍太小的话,则将我们所需的容量大小赋值给newCapacity
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;

        //如果1.5倍太大或者我们需要的容量太大,
        //那就直接拿 newCapacity = hugeCapacity(minCapacity) 
        //(minCapacity > MAX_ARRAY_SIZE) ? 
        Integer.MAX_VALUE : MAX_ARRAY_SIZE 来扩容
        // MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);

        //然后将原数组中的数据复制到大小为 newCapacity 的新数组中,
        //并将新数组赋值给 elementData。
        elementData = Arrays.copyOf(elementData, newCapacity);

    }
  1. 2.迭代
private class Itr implements Iterator<E> {
        // 代表下一个要访问的元素下标
        int cursor;      
        // 代表上一个要访问的元素下标
        int lastRet = -1;  
        //代表对 ArrayList 修改次数的期望值,初始值为 modCount
        //如果下一个元素的下标等于集合的大小 ,就证明到最后了
        int expectedModCount = modCount;

        Itr() {}

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

        @SuppressWarnings("unchecked")
        public E next() {
           
            checkForComodification();
            int i = cursor;
            //对 cursor 进行判断,看是否超过集合大小和数组长度
            if (i >= size)
                throw new NoSuchElementException();

            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
           //自增 1。开始时,cursor = 0,lastRet = -1;
           //每调用一次next方法,cursor和lastRet都会自增1。
            cursor = i + 1;
           将cursor赋值给lastRet,并返回下标为 lastRet 的元素
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            //判断 lastRet 的值是否小于 0
            if (lastRet < 0)
                throw new IllegalStateException();
            
             checkForComodification();

            try {
                //直接调用 ArrayList 的 remove 方法删除下标为 lastRet 的元素
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
               //将 lastRet 重新赋值为 -1,
                lastRet = -1;
               //将 modCount 重新赋值给 expectedModCount。
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

            //判断expectedModCount和modCount是否相等 
            //ConcurrentModificationException
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }    

1.LinkedList存储结构

双向链表

特点,插入删除快。查询慢

2.LinkedList代码实现

在这里插入图片描述

2.1 首先看类的继承,实现关系。

1. 继承了AbstractSequentialList,实现了List,Deque<?>,Cloneable, java.io.Serializable。
2. Deque 队列
3. Cloneable 拷贝
4. Serializable序列化

2.2 基本属性

Node(看next,prev很明显的双向链表)

在这里插入图片描述

2.3 构造方法

在这里插入图片描述

2.4 常用方法

  1. add 一个参数,默认尾插

在这里插入图片描述

  1. get方法

get这边算是二分查找吧
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值