先贴上代码: public boolean removeIf(Predicate<? super E> 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 int removeCount = 0; //使用了BitSet用来记录被删除的元素的下标 final BitSet removeSet = new BitSet(size); final int expectedModCount = modCount; final int size = this.size; //这个循环把符合条件的待删除的元素的下标设置到BitSet中,即BitSet中对应的下标设为true for (int i=0; modCount == expectedModCount && i < size; i++) { @SuppressWarnings("unchecked") final E element = (E) elementData[i]; if (filter.test(element)) { removeSet.set(i); removeCount++; } } //检测是否有其他线程并发修改这个ArrayList if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } // shift surviving elements left over the spaces left by removed elements final boolean anyToRemove = removeCount > 0; if (anyToRemove) { final int newSize = size - removeCount; //重点讲解这一步。刚开始看的时候一直认为这会导致死循环, //实际上这个循环里真正控制循环边界条件的是j,而不是i,因为j最后一定会到达newSize, //而i则不一定能到达size, 在实际使用中i有很大概率到不了size, // /**所以我认为这里的循环退出的判断应该是j<newSize在前面,形成“与”条件判断的短路**/ // 欢迎讨论 for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) { i = removeSet.nextClearBit(i); elementData[j] = elementData[i]; } for (int k=newSize; k < size; k++) { elementData[k] = null; // Let gc do its work } this.size = newSize; if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } return anyToRemove; }
ArrayList.removeIf 方法源码阅读
最新推荐文章于 2024-05-11 04:33:28 发布