zoukankan      html  css  js  c++  java
  • java集合之深入分析ArrayList

    ArrayList特点:

    ArrayList方法实现:

      扩容方法的实现:

        源码:

          

    1 private void ensureCapacityInternal(int minCapacity) {
    2         //如果数组为默认大小,则扩大的容量为minCapacity和默认值两个值的较大者
    3         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    4             minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    5         }
    6 
    7         ensureExplicitCapacity(minCapacity);
    8     }        
    1 private void ensureExplicitCapacity(int minCapacity) {
    2         modCount++;
    3 
    4         // overflow-conscious code
    5         //如果要扩大的容量比当前的数组长度大,则对数组进行扩容
    6         if (minCapacity - elementData.length > 0)
    7             grow(minCapacity);
    8     }        
     1 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
     2 
     3     /**
     4      * Increases the capacity to ensure that it can hold at least the
     5      * number of elements specified by the minimum capacity argument.
     6      *
     7      * @param minCapacity the desired minimum capacity
     8      */
     9     private void grow(int minCapacity) {
    10         // overflow-conscious code
    11         int oldCapacity = elementData.length;
    12         //增加的容量为原来大小的一半
    13         int newCapacity = oldCapacity + (oldCapacity >> 1);
    14         //如果增加了一半的容量还比要扩容的数量小,则新数组的大小为要扩容的数量
    15         if (newCapacity - minCapacity < 0)
    16             newCapacity = minCapacity;
    17         //如果新数组的大小大于Integer.MAX_VALUE - 8,则进行判断
    18         if (newCapacity - MAX_ARRAY_SIZE > 0)
    19             newCapacity = hugeCapacity(minCapacity);
    20         // minCapacity is usually close to size, so this is a win:
    21         //将原数组的元素全部复制到新数组中
    22         elementData = Arrays.copyOf(elementData, newCapacity);
    23     }
    24 
    25     private static int hugeCapacity(int minCapacity) {
    26         //如果minCapacity < 0,则容量值溢出
    27         if (minCapacity < 0) // overflow
    28             throw new OutOfMemoryError();
    29         
    30         return (minCapacity > MAX_ARRAY_SIZE) ?
    31             Integer.MAX_VALUE :
    32             MAX_ARRAY_SIZE;//Integer.MAX_VALUE - 8
    33     }        

      clone方法分析:

        ArrayList中的clone()方法为浅克隆,克隆后的集合对象与原有的集合对象不是同一个对象(即,指向不同的内存空间),但是它们集合元素引用的对象都是相同的。

        源码:

          

     1 public Object clone() {
     2         try {
     3             ArrayList<?> v = (ArrayList<?>) super.clone();
     4             //重新分配了一个链表,但是里面的元素是复制的引用(浅克隆)
     5             v.elementData = Arrays.copyOf(elementData, size);
     6             v.modCount = 0;
     7             return v;
     8         } catch (CloneNotSupportedException e) {
     9             // this shouldn't happen, since we are Cloneable
    10             throw new InternalError(e);
    11         }
    12     }            

      示例程序:

        

    ArrayList<String> list = new ArrayList<>();
                    //这样加入集合中时,引用的对象在常量池中
    //        list.add("dongfangbubai");
    //        String string = "dongfangbubai";
                    ////这样加入集合中时,引用的对象堆中
                    String string = new String("dongfangbubai");
            list.add(string);
            list.add("shangshanruoshui");
            
            ArrayList listClone = (ArrayList) list.clone();
            System.out.println(listClone);
            
            String content = "dongfangbubai";
            
            System.out.println(list.get(0).equals(content));
            System.out.println(list.get(0) == content);
    //克隆前后两个集合对应的元素所引用的都是同一个对象,true
                    System.out.println(list.get(0) == listClone.get(0));
            //克隆前后两个集合是不同的集合,false
            System.out.println(list == listClone);                                            

      ArrayList迭代时用迭代器只能一次删除一个元素(在一个迭代循环里),否则会出现java.lang.IllegalStateException异常。从源码可以看出这一点。

      

     1 public void remove() {
     2             if (lastRet < 0)
     3                 throw new IllegalStateException();
     4             checkForComodification();
     5 
     6             try {
     7                 ArrayList.this.remove(lastRet);
     8 
     9                 cursor = lastRet;
    10 //进行一次删除操作时,随即就把lastRet置为一,每次迭代时就把迭代的元素索引赋个给astRet
    11                 lastRet = -1;
    12                 expectedModCount = modCount;
    13             } catch (IndexOutOfBoundsException ex) {
    14                 throw new ConcurrentModificationException();
    15             }
    16         }

     

      

    // 数据结构发生改变,和fail-fast机制有关,在使用迭代器过程中,只能通过迭代器的方法(比如迭代器中add,remove等),修改List的数据结构, // 如果使用List的方法(比如List中的add,remove等),修改List的数据结构,会抛出ConcurrentModificationException

       

    fail-fast机制的实现

      

    fail-fast机制也叫作”快速失败”机制,是java集合中的一种错误检测机制。

    在对集合进行迭代过程中,除了迭代器可以对集合进行数据结构上进行修改(迭代器进行结构修改时不会增加modCount值),其他的对集合的数据结构进行修改,都会抛出ConcurrentModificationException错误。

    这里,所谓的进行数据结构上进行修改,是指对存储的对象,进行add,set,remove操作,进而对数据发生改变。

    ArrayList中,有个modCount的变量,每次进行add,set,remove等操作,都会执行modCount++。

    在获取ArrayList的迭代器时,会将ArrayList中的modCount保存在迭代中,

    每次执行add,set,remove等操作,都会执行一次检查,调用checkForComodification方法,对modCount进行比较。

    如果迭代器中的modCount和List中的modCount不同,则抛出ConcurrentModificationException

     源码:源码中modCount在list中,

    expectedModCount是在迭代时传入的modCount值,若迭代过程中list结构改变时,modCount会增加,以此迭代器1来判断迭代时list是否变化。

      

    1 final void checkForComodification() {
    2             if (modCount != expectedModCount)
    3                 throw new ConcurrentModificationException();
    4         }

    ArrayList与vector比较:

      

  • 相关阅读:
    WCF开发实战系列二:使用IIS发布WCF服务
    电脑远程登录控制Android手机Webkey For Android使用教程
    WCF的https安全(ssl)访问实例
    IIS中“使用 XSL 样式表无法查看 XML 输入”问题的解决
    服务器禁止被ping的设置方法(图文)
    Windows Server 2008 R2 MSDN
    IIS7配置https
    C# 检查网络是否连通 判断远程文件是否存在 C#获取程序路径的方法中需要注意的地方
    c#,winform,treeview,选中节点,选中相应的全部子节点,取消节点,取消父节点,小技巧
    sql大全(一)
  • 原文地址:https://www.cnblogs.com/gulingjingguai/p/7822248.html
Copyright © 2011-2022 走看看