对于调试jdk源码,若是发现无法在调试过程中查看源码中的变量,可以参考这篇文章:https://blog.csdn.net/u010407050/article/details/76690478
参考:http://www.cnblogs.com/skywang12345/p/3323085.html
removeIf() 方法 https://blog.csdn.net/qq_27093465/article/details/79154566
在接口collection里面的一个默认方法,当继承collection后,如果不自己实现这个方法就会采用这个默认的方法。
@Override 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; //记录删除元素的个数 final BitSet removeSet = new BitSet(size); //记录被删除的元素的索引 在需要删除的元素那个索引那置为true final int expectedModCount = modCount; //在未做处理前被更改的次数 final int size = this.size; //集合包含元素的个数 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++; } } 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; //新的集合的大小 for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) { 将那些标志位false的元素往左移,填补那些需要删除的元素的位置 i = removeSet.nextClearBit(i); elementData[j] = elementData[i]; } for (int k=newSize; k < size; k++) { 将新的集合的新长度之后的元素都置为null,便于gc进行垃圾回收 elementData[k] = null; // Let gc do its work } this.size = newSize; if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } return anyToRemove; }
参考:http://www.cnblogs.com/skywang12345/p/3308556.html
http://www.cnblogs.com/zhangyinhua/p/7687377.html
ArrayList
//void java.util.ArrayList.trimToSize() /** * Trims the capacity of this <tt>ArrayList</tt> instance to be the * list's current size. An application can use this operation to minimize * the storage of an <tt>ArrayList</tt> instance. */ public void trimToSize() { 将ArrayList的容量减至最低,与元素的个数相同 这样可以节约存储空间 modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); 只取这个数组只的size大小的元素的数组 } }
//void java.util.ArrayList.ensureCapacity(int minCapacity) /** * Increases the capacity of this <tt>ArrayList</tt> instance, if * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ public void ensureCapacity(int minCapacity) { int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // any size if not default element table 如果是已经插入过值的ArrayList,那么最小扩容是任意, ? 0 // larger than default for default empty table. It's already // supposed to be at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) 只有现在设置的容量比之前的数组容量大才需要扩容 grow(minCapacity); } /** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ private void grow(int minCapacity) { 这里是实际进行扩容的操作 // overflow-conscious code int oldCapacity = elementData.length; 这是原来的容量 int newCapacity = oldCapacity + (oldCapacity >> 1); 原来容量的1.5倍 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; 若是现在这个容量比你设置的那个容量要小的话,就采用你设置的那个容量,不然就设置为原来容量的1.5倍 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: 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; }
public boolean contains(Object o) { return indexOf(o) >= 0; } public int indexOf(Object o) { 查找出元素在ArrayList中出现的第一次的位置 顺序遍历 if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; } public int lastIndexOf(Object o) { 查找出元素在ArrayList中出现的最后一次,沿着数组反向遍历即可 if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; }
@SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { if (a.length < size) 如果a的长度比原ArrayList的长度要小 这个a数组就放不下原ArrayList转成成的数组 // Make a new array of a's runtime type, but my contents:生成一个新的数组,将原来的ArrayList中的元素拷贝进去,返回 return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); 将ArrayList中的元素拷贝到a数组中,覆盖原有值 if (a.length > size) 将a数组后面多的元素清空 a[size] = null; return a; }
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); 在删除index处的数据后,将所有的index后面的元素向前移动 elementData[--size] = null; // clear to let GC do its work return oldValue; }
public boolean remove(Object o) { 删除指定元素 if (o == null) { 如果是null的话,就把数组中所有的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; } private void fastRemove(int index) { 快速删除索引为index的元素,因为这里快速就是没经过检查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 }
/** * Removes all of the elements from this list. The list will * be empty after this call returns. */ public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; }clear操作只是将数组中所有元素置为null,然后将数组的大小(元素的个数)设置为0
public boolean addAll(int index, Collection<? extends E> c) { 将一个集合插入到index处 rangeCheckForAdd(index); Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount int numMoved = size - index; if (numMoved > 0) 先将index后面的数据整体往后移动numNew个单位 System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); 将数据拷贝进来 size += numNew; return numNew != 0; }