数据结构---Java---ArrayList

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

   //初始容量10
     private static final int DEFAULT_CAPACITY = 10;
       //空的Object[]
     private static final Object[] EMPTY_ELEMENTDATA = {};
       //默认的空数组容量
     private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 
   //底层使用数组实现
     transient Object[] elementData;
     private int size;
     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

       ++++++++++++++++++构造器+++++++++
     
      //无参构造器---Object[]的大小为0
     public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

     // 有参构造器
    public ArrayList(int initialCapacity) {
         //如果自定义容量大于0,创建一个自定义容量的Object数组
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        }
         //如果自定义容量=0,Object[]大小为0
        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;
        }
    }

     
   +++++++++++++++方法+++++++++++++++++

    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 static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
  //扩容
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
    //新容量=旧容量+(旧容量>>1) 旧容量的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);
    }
    
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
       
} 

 

 

 

1、ArrayList遍历时的删除问题

      1.1  普通for

package com.an.cycle;

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args){

        List<String> list=new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");

        for(int i=0;i<list.size();i++){
            if(list.get(i).equals("a"))
                list.remove(i);
        }
    }
}

由于删除后集合大小、元素位置发生移动,导致数据索引出现问题

  

List<String> list = new ArrayList<>();
        list.add("c");
        list.add("6");
        list.add("4");
        list.add("2");

        for (int i = 0; i< list.size(); i++){
            if (list.get(i).equals("c")){
                list.remove("c");
            }
        }

        System.out.println(list);




public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: new           #2                  // class java/util/ArrayList
         3: dup
         4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
         7: astore_1
         8: aload_1
         9: ldc           #4                  // String c
        11: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        16: pop
        17: aload_1
        18: ldc           #6                  // String 6
        20: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        25: pop
        26: aload_1
        27: ldc           #7                  // String 4
        29: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        34: pop
        35: aload_1
        36: ldc           #8                  // String 2
        38: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        43: pop
        44: iconst_0
        45: istore_2
        46: iload_2
        47: aload_1
        48: invokeinterface #9,  1            // InterfaceMethod java/util/List.size:()I
        53: if_icmpge     89
        56: aload_1
        57: iload_2
        58: invokeinterface #10,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
        63: checkcast     #11                 // class java/lang/String
        66: ldc           #4                  // String c
        68: invokevirtual #12                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        71: ifeq          83
        74: aload_1
        75: ldc           #4                  // String c
        77: invokeinterface #13,  2           // InterfaceMethod java/util/List.remove:(Ljava/lang/Object;)Z
        82: pop
        83: iinc          2, 1
        86: goto          46
        89: getstatic     #14                 // Field java/lang/System.out:Ljava/io/PrintStream;
        92: aload_1
        93: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        96: return

  

      1.2  增强for 

package com.an.cycle;

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args){

        List<String> list=new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");

        for(String x:list){
            if(x.equals("a"))
                list.remove(x);
        }
    }
}

结果:使用增强for进行删除,引发异常
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
	at java.util.ArrayList$Itr.next(ArrayList.java:859)
	at com.an.cycle.Test.main(Test.java:20)


分析:进入异常信息查看
final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

1、ArrayList的父类AbstractList有一个属性modCount:
   protected transient int modCount = 0;   用于记录对ArrayList的操作次数

2、ArrayList有一个内部类Itr,实现了Iterator:
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{

    private class Itr implements Iterator<E> {
        int expectedModCount = modCount;
        
        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];
        }
        
        //异常提示位置
         final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }
}

3、 list.remove(x);会调用ArrayList的fastRemove方法:
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
    }

    此时 modCount++,而expectedModCount没有变化,导致异常触发

  

List<String> list = new ArrayList<>();
        list.add("c");
        list.add("6");
        list.add("4");
        list.add("2");

        for (String s : list){
            if (s.equals("c")){
                list.remove("c");
            }
        }

        System.out.println(list);





public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: new           #2                  // class java/util/ArrayList
         3: dup
         4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
         7: astore_1
         8: aload_1
         9: ldc           #4                  // String c
        11: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        16: pop
        17: aload_1
        18: ldc           #6                  // String 6
        20: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        25: pop
        26: aload_1
        27: ldc           #7                  // String 4
        29: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        34: pop
        35: aload_1
        36: ldc           #8                  // String 2
        38: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        43: pop
        44: aload_1
        45: invokeinterface #9,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;                 增强for本质使用的是java/util/List.iterator
        50: astore_2
        51: aload_2
        52: invokeinterface #10,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
        57: ifeq          91
        60: aload_2
        61: invokeinterface #11,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
        66: checkcast     #12                 // class java/lang/String
        69: astore_3
        70: aload_3
        71: ldc           #4                  // String c
        73: invokevirtual #13                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        76: ifeq          88
        79: aload_1
        80: ldc           #4                  // String c
        82: invokeinterface #14,  2           // InterfaceMethod java/util/List.remove:(Ljava/lang/Object;)Z
        87: pop
        88: goto          51
        91: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
        94: aload_1
        95: invokevirtual #16                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        98: return

  

  

  

    1.3  Iterator遍历

package com.an.cycle;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Test {

    public static void main(String[] args){

        List<String> list=new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");

        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String x = it.next();
            if(x.equals("a")){
                list.remove(x);
            }
        }
    }
}

结果:使用ArrayList的remove仍会抛出异常:
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
	at java.util.ArrayList$Itr.next(ArrayList.java:859)
	at com.an.cycle.Test.main(Test.java:28)

 

      1.4  解决ArrayList的删除问题

                                    使用Iterator的remove 方法

package com.an.cycle;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Test {

    public static void main(String[] args){

        List<String> list=new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");

        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String x = it.next();
            if(x.equals("a")){
                it.remove();
            }
        }

        System.out.println(list);
    }
}

  

List<String> list = new ArrayList<>();
        list.add("c");
        list.add("6");
        list.add("4");
        list.add("2");

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            if (iterator.next().equals("c")){
                iterator.remove();
            }
        }

        System.out.println(list);



public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: new           #2                  // class java/util/ArrayList
         3: dup
         4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
         7: astore_1
         8: aload_1
         9: ldc           #4                  // String c
        11: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        16: pop
        17: aload_1
        18: ldc           #6                  // String 6
        20: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        25: pop
        26: aload_1
        27: ldc           #7                  // String 4
        29: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        34: pop
        35: aload_1
        36: ldc           #8                  // String 2
        38: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        43: pop
        44: aload_1
        45: invokeinterface #9,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
        50: astore_2
        51: aload_2
        52: invokeinterface #10,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
        57: ifeq          86
        60: aload_2
        61: invokeinterface #11,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
        66: checkcast     #12                 // class java/lang/String
        69: ldc           #4                  // String c
        71: invokevirtual #13                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        74: ifeq          51
        77: aload_2
        78: invokeinterface #14,  1           // InterfaceMethod java/util/Iterator.remove:()V
        83: goto          51
        86: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
        89: aload_1
        90: invokevirtual #16                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        93: return

  

  

 

posted on 2019-02-22 11:01  anpeiyong  阅读(188)  评论(0编辑  收藏  举报

导航