Java集合-ArrayListy(二)

来源:互联网 发布:苏联的秘密武器知乎 编辑:程序博客网 时间:2024/06/07 14:22

ArrayList源码解析

主要方法

删除元素
1

public E remove(int index) {//检查下标是否合法   rangeCheck(index);   modCount++;   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;   }

2

   public boolean remove(Object o) {   //for循环遍历去删除指定元素,相同元素删除下标小的   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;   }

3从该列表中移除包含在指定集合中的所有元素。

   public boolean removeAll(Collection<?> c) {   Objects.requireNonNull(c);   return batchRemove(c, false);

4仅保留包含在指定集合中的此列表中的元素。换句话说,从该列表中移除所有未包含在指定集合中的元素。

   public boolean retainAll(Collection<?> c) {   Objects.requireNonNull(c);   return batchRemove(c, true);   }

5removeAll和retainAll区别在于batchRemove(a,b)的第二个参数

   private boolean batchRemove(Collection<?> c, boolean complement) {   final Object[] elementData = this.elementData;   int r = 0, w = 0;   boolean modified = false;   try {       for (; r < size; r++)       /* 如果complement为false,将c中不包含的ArrayList的元素放在一个elementData[]数组中,完成删除;如果complement为true,反之。       */           if (c.contains(elementData[r]) == complement)               elementData[w++] = elementData[r];   } finally {       // 保存和收集的行为兼容性,        / /即使C. contains()抛出。       if (r != size) {           System.arraycopy(elementData, r,                            elementData, w,                            size - r);           w += size - r;       }       if (w != size) {           // clear to let GC do its work           for (int i = w; i < size; i++)               elementData[i] = null;           modCount += size - w;           size = w;           modified = true;       }   }   return modified;   }

遍历ArrayList的方法

for(Object o:list)for(int i=0;i<=list.size();i++)Iterator<String> i = list.iterator();while(i.hasNext())

问题:遍历的时候去删除元素,会出现什么问题?

List<String> list = new ArrayList();    list.add("1");    list.add("2");    list.add("3");    list.add("4");    list.add(1, "6");    list.remove("11");    for(String i:list){            list.remove(i);    }    for(int i=0;i<=list.size();i++){            list.remove(i);    }    System.out.println(list.isEmpty());    Iterator<String> i = list.iterator();    while(i.hasNext()){            i.remove();    }

foreach会抛ConcurrentModificationException
for循环却是删除不完元素
使用iterator则没有问题

foreach在循环遍历时,底层也是 private class Itr implements Iterator这个内部类的方法。

private class Itr implements Iterator<E> {   int cursor;       // index of next element to return   int lastRet = -1; // index of last element returned; -1 if no such   int expectedModCount = modCount;   public boolean hasNext() {       return cursor != size;   }   @SuppressWarnings("unchecked")   public E next() {   //foreach循环时,删除完元素的下一次遍历在这里抛异常是因为modCount和expectedModCount 的大小不一样了,(内部类无法同步外部变量)       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];   }   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();       }   }   final void checkForComodification() {       if (modCount != expectedModCount)           throw new ConcurrentModificationException();   }   }

for循环在删除时,size的大小随着每次删除完,大小在变化,所以没法删除完全。


有问题欢迎提出。

原创粉丝点击