ArrayList中的removeIf

转载请标明出处^_^
原文首发于: www.zhangruibin.com
本文出自于: RebornChang的博客

ArrayList

ArrayList中的removeIf

ArrayList 继承了 AbstractList,实现了 List、 RandomAccess、 Cloneable、java.io.Serializable接口;
AbstractList继承了 AbstractCollection,实现了 List接口;
AbstractCollection实现了Collection接口;
Collection接口继承了Iterable接口;
Collection为顶级集合接口,实现了Iterable接口,可以迭代。

Collction接口中在Jdk1.8之后新增了个removeIf,有啥用?
removeIf源码@since 1.8:

default boolean removeIf(Predicate filter) {
       Objects.requireNonNull(filter);
       boolean removed = false;
       final Iterator each = iterator();
       while (each.hasNext()) {
           if (filter.test(each.next())) {
               each.remove();
               removed = true;
           }
       }
       return removed;
   }

ArrayList对其进行重写:

@Override
   public boolean removeIf(Predicate filter) {
       //首先要验证规则不能为空
       Objects.requireNonNull(filter);
       // figure out which elements are to be removed
       // any exception thrown from the filter predicate at this stage
       // will leave the collection unmodified
       //计数器,记录revove掉的次数
       int removeCount = 0;
       //声明要remove掉的集合,声明为set,保证不重复remove
       final BitSet removeSet = new BitSet(size);
       final int expectedModCount = modCount;
       final int size = this.size;
       //循环遍历list
       for (int i=0; modCount == expectedModCount && i < size; i++) {
           @SuppressWarnings("unchecked")
           final E element = (E) elementData[i];
           //boolean test(T t);校验参数是否匹配,匹配则返回true,如果匹配,则在removeSet中存入索引,removeCount值加一
           if (filter.test(element)) {
               removeSet.set(i);
               removeCount++;
           }
       }
       //校验此时的集合是否在多线程IO下受到改变,若受到改变则抛出异常
       if (modCount != expectedModCount) {
           throw new ConcurrentModificationException();
       }
       //源码中这句,表明了,将不需要移除的空间左移
       // shift surviving elements left over the spaces left by removed elements
       //定义anyToRemove,如果removeCount > 0则为true
       final boolean anyToRemove = removeCount > 0;
       //如果anyToRemove为true则继续进行,否则意味着没有匹配的可移除元素,直接return anyToRemove = false;
       if (anyToRemove) {
       //若有元素符合移除条件,则声明新size,重新定义list大小(ArrayList初始默认容量为10)
           final int newSize = size - removeCount;
           //循环遍历元素赋值,这里用到了一个新的方法nextClearBit(fromIndex)
           //将需要移除的元素在重新存储的时候跳过
           for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
           
               i = removeSet.nextClearBit(i);
               elementData[j] = elementData[i];
           }
           //如果新的集合与原集合比较,将指定要移除的设置为null,GC回收内存
           for (int k=newSize; k < size; k++) {
               elementData[k] = null;  // Let gc do its work
           }
           //更新全局变量的集合大小为移除后的新集合大小
           this.size = newSize;
           //再次判断是否受到多线程IO影响
           if (modCount != expectedModCount) {
               throw new ConcurrentModificationException();
           }
           modCount++;
       }

       return anyToRemove;
   }
   //官方解释:返回设置为在指定的起始索引上或之后出现的第一个位的索引。
    public int nextClearBit(int fromIndex) {
       // Neither spec nor implementation handle bitsets of maximal length.
       // See 4816253.
       if (fromIndex < 0)
           throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);

       checkInvariants();

       int u = wordIndex(fromIndex);
       if (u >= wordsInUse)
           return fromIndex;

       long word = ~words[u] & (WORD_MASK << fromIndex);

       while (true) {
           if (word != 0)
               return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word);
           if (++u == wordsInUse)
               return wordsInUse * BITS_PER_WORD;
           word = ~words[u];
       }
   }
    private static int wordIndex(int bitIndex) {
       return bitIndex >> ADDRESS_BITS_PER_WORD;
   }

//验证结果

public static void main(String[] args) {
      List list = new ArrayList();
      list.add("Name");
      list.add("aaa");
      list.add("bbb");
      list.add("ccc");
      list.add("ddd");
      System.out.println(list.toString());
      //removeIf 的使用方法
      list.removeIf(next ->next.toString().indexOf("a")>0);
      System.out.println("===============removeIf 1====================");
      System.out.println(list.toString());
      //或者这样写
      Predicate predicate = (s) -> s.equals("ddd");
      list.removeIf(predicate);
      System.out.println("===============removeIf 2====================");
      System.out.println(list.toString());
      List list2 = new LinkedList();
      list2.addAll(list);
      System.out.println("===================addAll================");
      System.out.println(list2.toString());
      List list3 = new LinkedList();
      list3.addAll(list);
      list3.clear();
      System.out.println("===================clear================");
      System.out.println(list3.toString());
      list3.addAll(list);
      list3.addAll(list);
      list3.removeAll(list2);
      System.out.println("===================removeAll 1================");
      System.out.println(list3.toString());
      List list4 = new LinkedList();
      list4.addAll(list);
      list2.add("test");
      System.out.println("===================removeAll 2================");
      System.out.println(list4.toString());
  }
  
  输出:
  [Name, aaa, bbb, ccc]
  ===============removeIf====================
  [aaa, bbb, ccc]
  ===================addAll================
  [aaa, bbb, ccc]
  ===================clear================
  []
  ===================removeAll 1================
  []
  ===================removeAll 2================
  [aaa, bbb, ccc]

可以看到:
1.removeIf方法是给定一个判断条件,符合条件即删除。
2.clear和removeAll的区别是:clear是无条件清空,removeAll是移除两个集合的交集。

你可能感兴趣的:(Java)