zoukankan      html  css  js  c++  java
  • java-ArrayList源码

    ArrayLisrt 应该不陌生,对,就是可调整大小的动态数组,具体怎么实现的呢,就让咱们一探究竟吧!

    初始化:

      构造方法:

      构建一个初始化容量为10的空数组

    //默认初始化数据容器
    private static final Object[] EMPTY_ELEMENTDATA = {};/**
    /* 存储数组元素的数组缓冲区
    * ArrayList的容量就是这个数组缓冲区的长度
    *任何一个空的ArrayList将在添加第一个扩展元素添加后,为默认容量
    */
    transient Object[] elementData; // 非私有 简化嵌套类访问

    public
    ArrayList() {   this.elementData = DEFAULTCAPACITY_EMPTY_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);
            }
        }

      //构建一个包含指定集合的元素列表,

    //将参数转为集合数组 
    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; } }

      add():

      将指定的元素添加到列表的末尾

    /*
      *
      *@param e 新增数据元素
      *
    */
    public boolean add(E e) {
      //确保数组具有存储空间,包括核心扩容算法   ensureCapacityInternal(size
    + 1); // Increments modCount!!
      // 数组末尾追加,索引下标++;新增元素后索引加以
      elementData[size++] = e;   return true; }
    private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    //确认数组具有存储空间,数组已开辟空间不够,进行扩容
    private void ensureExplicitCapacity(int minCapacity) {
    modCount++;//集合的修改次数

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
    grow(minCapacity);
    }
    //返回数组最小容量,默认容量10
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
    }
    
    
    private void grow(int minCapacity) {
    //计算已有数组长度
    int oldCapacity = elementData.length;
      // >>:右移,相当于除以2的n次幂
      // <<:左移,相当于乘以2的n次幂
      //核心,扩容相当于原数组的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
      //赋值操作
    if (newCapacity - minCapacity < 0)
    newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
    newCapacity = hugeCapacity(minCapacity);
      //拷贝操作
    elementData = Arrays.copyOf(elementData, newCapacity);
    }
      add(int index, E element);

      列表时指定位置插入指定元素 

    public void add(int index, E element) { 
         //校验新增索引位置 rangeCheckForAdd(index);      //确认存储空间大,并扩容原大小1.5倍 ensureCapacityInternal(size
    + 1); // Increments modCount!!
         //数组拷贝
    System.arraycopy(elementData, index, elementData, index + 1,size - index); elementData[index] = element; size++; }

    // 判断索引位置,大于数组大小或者小于0抛出异常
    private void rangeCheckForAdd(int index) {
      if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
     
      addAll(Collection<? extends E> c)
      按照指定的集合的iterator返回的顺序将指定集合中的所有元素追加到列表末尾
    public boolean addAll(Collection<? extends E> c) {
        // 将新增的元素转化为数组 Object[] a
    = c.toArray();
        // 获取数组a的长度
    int numNew = a.length;
        // 校验空间大小,并1.5倍扩容 ensureCapacityInternal(size
    + numNew); // Increments modCount
        //拷贝元素
    System.arraycopy(a, 0, elementData, size, numNew); //数组长度操作后,进行累加
         size
    += numNew; return numNew != 0; }
      addAll(int index, Collection<? extends E> c)
      将指定集合中的所有元素插入到里列表,从指定的位置开始
        public boolean addAll(int index, Collection<? extends E> c) {
            rangeCheckForAdd(index);
    
            Object[] a = c.toArray();
            int numNew = a.length;
            ensureCapacityInternal(size + numNew);  // Increments modCount  
          //计算需要移动的个数(elementData)
            int numMoved = size - index;
            if (numMoved > 0)//判断移动个数是否大于0     
                System.arraycopy(elementData, index, elementData, index + numNew,
                                 numMoved);
    
            System.arraycopy(a, 0, elementData, index, numNew);
            size += numNew;
            return numNew != 0;
        }
      set(int index, E element)
      修改方法
        public E set(int index, E element) {
         //判断索引下标 rangeCheck(index);      //获取数组中index索引所在位置的数据元素 E oldValue
    = elementData(index);
         //替换数组中index索引所在位置的数据元素内容 elementData[index]
    = element; return oldValue;//返回修改园所原始内容 }
      get(int index)
    获取方法
    public E get(int index) {
         //判断索引位置 rangeCheck(index); //返回索引位置数据
    return elementData(index); }
      toString()
      转换方法,将集合中所有元素转换为字符串
    public String toString() {
         //获取迭代器 Iterator
    <E> it = iterator(); if (! it.hasNext()) return "[]";      //进行字符串组装 StringBuilder sb = new StringBuilder(); sb.append('[');
         //无线循环
    for (;;) { E e = it.next(); sb.append(e == this ? "(this Collection)" : e); if (! it.hasNext()) return sb.append(']').toString(); sb.append(',').append(' '); } }
      Iterator<E> iterator()
      获取迭代器
    public Iterator<E> iterator() {
            return new Itr();
        }
    //迭代器
    private class Itr implements Iterator<E> {
    int cursor; // 当前位置
    int lastRet = -1; // 记录- 1
    int expectedModCount = modCount;//将集合实际修改次数复制给预期修改次数

    Itr() {}
    //判断集合是否有元素
    public boolean hasNext() {
    return cursor != size;
    }


    public E next() {
         //检查预期修改次数和实际修改次数相等
    checkForComodification();
         //将光标复制给i变量
    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();
    }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void forEachRemaining(Consumer<? super E> consumer) {
    Objects.requireNonNull(consumer);
    final int size = ArrayList.this.size;
    int i = cursor;
    if (i >= size) {
    return;
    }
    final Object[] elementData = ArrayList.this.elementData;
    if (i >= elementData.length) {
    throw new ConcurrentModificationException();
    }
    while (i != size && modCount == expectedModCount) {
    consumer.accept((E) elementData[i++]);
    }
    // update once at end of iteration to reduce heap write traffic
    cursor = i;
    lastRet = i - 1;
    checkForComodification();
    }

    final void checkForComodification() {
    if (modCount != expectedModCount)
    throw new ConcurrentModificationException();
    }
    }
     
      remove(Object o)

      删除元素

    public boolean remove(Object o) {
            if (o == null) {
                for (int index = 0; index < size; index++)
                    if (elementData[index] == null) {
                        fastRemove(index);
                        return true;
                    }
            } else {
                for (int index = 0; index < size; index++)
                    if (o.equals(elementData[index])) {
                        //删除操作
                fastRemove(index);
    return true; } } return false; }
      void clear() 
      清空方法
    public void clear() {
            modCount++;
    
            // clear to let GC do its work
            for (int i = 0; i < size; i++)
                elementData[i] = null;
    
            size = 0;
        }
      boolean contains(Object o)
      判断集合中是否包含元素
    public boolean contains(Object o) {
            return indexOf(o) >= 0;
        }
    public int indexOf(Object o) {
    if (o == null) {
    for (int i = 0; i < size; i++)
    if (elementData[i]==null)
    return i;
    } else {
    for (int i = 0; i < size; i++)
    if (o.equals(elementData[i]))
    return i;
    }
    return -1;
    }
     
      boolean isEmpty()
      空实体判断
    public boolean isEmpty() {
            return size == 0;
        }
    1.ArrayList是如何扩容的?
      第一次扩容10
      以后每次扩容原有用量的1.5倍

    2。数组新增海量数据,优化?
      ArrayList底层,需要进行多次扩容,效率低下!
      优化方案:使用构造,指定初始化容量

    3.ArrayList插入或者删除元素一定比LinkedList慢?

      不一定,因为LinkedList查找元素(node)很费时

    ArrayList remove()
    public E remove(int index) {
        //索引校验 rangeCheck(index);     //数组实际操作次数,多线程使用 modCount
    ++;
    //获取下标索引为index的元素 E oldValue
    = elementData(index); //计算需要移动的个数 int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved);
         //最后一项元素置空 elementData[
    --size] = null; // clear to let GC do its work //返回删除元素内容 return oldValue; }

    LinkedList remove()方法

    public E remove(int index) {
        //检查索引 checkElementIndex(index);
    return unlink(node(index)); }
    //
    E unlink(Node<E> x) {
      //需要删除的元素
    final E element = x.item;
      //下一个元素
    final Node<E> next = x.next;
      //上一个元素
    final Node<E> prev = x.prev;
    if (prev == null) {//首节点
    first = next;//把下一个节点置为首节点
    } else {//非首节点
    prev.next = next;//把当前节点置为下一个节点
    x.prev = null;//把
    }
      
    if (next == null) {//尾节点
    last = prev;//前一个节点置为尾节点
    } else {
    next.prev = prev;//
    x.next = null;
    }
    //元素置为空
    x.item = null;
      //大小减1
    size--;
      //实际操作次数
    modCount++;
    return element;
    }
    //LinkedList 存储的第一个节点
    transient Node<E> first;
    //查找元素
    Node<E> node(int index) {
    // assert isElementIndex(index);
      //判断索引是否小于数组大小的一般
    if (index < (size >> 1)) {
        //把第一个节点赋值给x
    Node<E> x = first;
        //从第一个节点开始往后读取,直到下标为index的元素
    for (int i = 0; i < index; i++)
    x = x.next;
    return x;
    } else {
        //把最后一个节点赋值给x
    Node<E> x = last;
        //从最后一个节点开始,以次往前读取,直到下标为index的元素
    for (int i = size - 1; i > index; i--)
    x = x.prev;
    return x;
    }
    }
    //node对象
    private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
    this.item = element;
    this.next = next;
    this.prev = prev;
    }
    }
     

     4.ArrayList是线程安全的吗?如何解决线程共享?

      不是线程安全的

      解决方案:

        1.添加同步代码块或者同步方法

        2.使用vector替代ArrayList;不考虑线程安全的情况,更推荐ArrayList

        3.通过工具类实现Collections.synchronizedList(new ArrayList<String>())创建数组

    5.如何复制ArrayList到另一个ArrayList?

      1.使用clone()

      2.使用ArrayList构造

      3.使用AddAll方法

      4.以及循环遍历逐个添加

    6.已知成员变量集合存储N多用户名称,在多线程环境下,使用迭代器读取集合数据同时保证还可以正常的写入数据到集合?

      使用CopyOnWriteArrayList

    7.ArrayList和LinkedList区别?

      ArrayList

      基于动态数组的结构

      对于随机访问的get和set,ArrayList由于LinkedList

      对于随机的add和remove,AraayList不一定比Linkedlistman(ArrayList底层由于是动态数组,因此并不是每次add和remove都需要创建新的数组)

      LinedList

      基于链表的数据结构

      对于顺序操作,LinkedList不一定比ArrayList慢

      对于随机操作,LikedList效率明显较低

    自定义ArrAyList

      1.定义成员变量

      2.构造方法

      3.定义添加、移除、修改、扩容方法

      

      





      

  • 相关阅读:
    &【12】Python 函数
    &【11】Python 流程控制
    &【09】Python 数据类型之dictionary
    &【07】Python 数据类型之元组
    &【08】Python 数据类型之set
    &【06】Python 数据类型之list
    &【05】Python 彻底搞懂分片操作
    &【04】Python 数据结构之序列
    SpringBoot-HelloWorld(三)
    SpringBoot-了解微服务(二)
  • 原文地址:https://www.cnblogs.com/ywzq/p/14315483.html
Copyright © 2011-2022 走看看