zoukankan      html  css  js  c++  java
  • java ArrayList源码解读

      1 、ArrayList 简介

        ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长

      2、ArrayList源码解读

         2.1、  我们先来看一下 ArrAyList的结构 

        public class ArrayList<E> extends AbstractList<E>
                implements List<E>, RandomAccess, Cloneable, java.io.Serializable

                     继承自 AbstractList<E> ,这是一个抽象类对一些基础的list操作做了一些封装,实现了RandomAccess 标记接口,表明可以实现快速随机访问,Cloneable接口的实现表示该容器具有Clone函数操作,Serializable是序列化。

          

         2.2、  一些成员变量

      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 = {};
    
        /**
         * arrayList 存蓄元素的数组
         */
        transient Object[] elementData; // non-private to simplify nested class access
    
        /**
         * 数组的大小
         */
        private int size;

          2.3  构造方法

       /**
         * 指定初始化数组的大小*/
        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() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } /** *构造一个具有指定元素的ArrayList    */ 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  常用方法

      增加操作  这里ArrayList扩充自己的容量是,扩充为以前的1.5倍  , 默认是 长度为10的数组

        /**
         **/
        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); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; }

    /**
    * rangeCheckForAdd 判断下标是否越界(超过当前数组的大小)

    */
    private void rangeCheckForAdd(int index) {
    if (index > size || index < 0)
    throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
      /**
       * 判断数组的元素的是否初始化 , 当为空的构造方法的时候,初始化数组大小
       */
    private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
      //判断是否需要扩容  
    ensureExplicitCapacity(minCapacity);
    }

       /**
        * modCount 记录操作 这个参数运用到了 fail-fast 机制
        */ 
    private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    //扩容  
    if (minCapacity - elementData.length > 0)
    grow(minCapacity);
    }
    
    
    
    

    /**
    *  将整个数组size扩容为1.5倍 
    */
    private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    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);
    }



      

         

     删除 

    /**
         *  根据索引删除元素*/
        public E remove(int index) {
            rangeCheck(index);
    
            modCount++;
        // 获取元素 E oldValue
    = elementData(index);      // 计算数组需要复制的数量  
    int numMoved = size - index - 1; if (numMoved > 0)
          // 将index后的数据都向前移一位   System.arraycopy(elementData, index
    +1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work return oldValue; } /** * */ 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; }

      
    /*
    * 找到对应的元素后,删除。删除元素后的元素都向前移动一位
    */
    private void fastRemove(int index) {
    modCount++;
    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
    }
    
    


     数组节约内存空间,缩小容量的方法 :   trimToSize

      /**
         * 数组缩小容量,增加元素会进行扩容,但删除元素没有缩容     这个方法是用来提供缩小数组容量 
    */
        public void trimToSize() {
            modCount++;
            if (size < elementData.length) {
                elementData = (size == 0)
                  ? EMPTY_ELEMENTDATA
                  : Arrays.copyOf(elementData, size);
            }
        }

    本文参考  http://blog.csdn.net/u012883858/article/details/51393055     

    有什么不好的地方还望指正~~~

  • 相关阅读:
    多线程编程(6) 从 CreateThread 说起[续四]
    多线程编程(7) 从 CreateThread 说起[续五]
    我最喜欢的邮件客户端软件IncrediMail Xe
    [公告]博客园建立了“专家区”
    [新功能]文章档案
    Lucene.Net的语言处理包中Lucene.Net.Analysis.Cn的Bug
    [好消息]博客园与博文视点、第二书店合作推出“读书心得区”
    推荐一篇有关GC的文章
    [小技巧]在NTFS分区中复制文件的同时如何复制权限
    ShartPoin无法创建门户网站的问题
  • 原文地址:https://www.cnblogs.com/scholar-xie/p/7000082.html
Copyright © 2011-2022 走看看