ArrayList 冷门方法
以下代码片都是 jdk1.8 ArrayList中的官方代码
/** * Constructs a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * @param c the collection whose elements are to be placed into this list * @throws NullPointerException if the specified collection is null */ 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; } }
解读:ArrayList的构造方法,用得比较少,至少我用得比较少。参数是Collection的实现类都行,
由此我想到了一个好玩的东西,如果要将两个集合想加,那么可以试试这个方法,虽然官方提供了
public boolean addAll(int index, Collection<? extends E> c) 和public boolean addAll(Collection<? extends E> c) 这两个方法。
/** * 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() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } }
解读:这是个好东西。
ArrayList所说没有用的值并不是null,而是ArrayList每次容量不够用时申请的存储空间会稍稍多一些,1.5倍+1,
这样就会出现当size() = 1000的时候,ArrayList已经申请了1200空间的情况 此时trimToSize
的作用只是去掉预留元素位置,就是删除多余的200,官方指导的是可以用来优化存储
/** * 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 ? 0 // larger than default for default empty table. It's already // supposed to be at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } }
解读:这更是个好东西。因为官方都建议使用了,
* <p>An application can increase the capacity of an <tt>ArrayList</tt> instance
* before adding a large number of elements using the <tt>ensureCapacity</tt>
* operation. This may reduce the amount of incremental reallocation.
简单来说就是业务情况预先设置集合的容量,这样能够大大提高初始化速度。可能有人说直接指定容量呢,实际情况中你哪会知道容量会多大,就算知道,那效率更是不敢看
下面是测试代码,运行看看就知道了
package sourceCode.ArrayList; import java.util.ArrayList; /** * ArrayList.ensureCapacity(N)性能测试 * */ public class entureCapacityTest { @SuppressWarnings({ "unchecked", "rawtypes" }) public static void main(String[] args) { final int N = 100000000; Object obj = new Object(); // 1.没用调用ensureCapacity()方法初始化ArrayList对象 ArrayList list = new ArrayList(); long startTime = System.currentTimeMillis(); for (int i = 0; i <= N; i++) { list.add(obj); } long endTime = System.currentTimeMillis(); System.out.println("没有调用ensureCapacity()方法所用时间:" + (endTime - startTime) + "ms"); // 2.调用ensureCapacity()方法初始化ArrayList对象 list = new ArrayList(); startTime = System.currentTimeMillis(); // 预先设置list的大小 list.ensureCapacity(N); for (int i = 0; i <= N; i++) { list.add(obj); } endTime = System.currentTimeMillis(); System.out.println("调用ensureCapacity()方法所用时间:" + (endTime - startTime) + "ms"); // 3.直接指定容量 list = new ArrayList(N); startTime = System.currentTimeMillis(); for (int i = 0; i <= N; i++) { list.add(obj); } endTime = System.currentTimeMillis(); System.out.println("直接设置容量所用时间:" + (endTime - startTime) + "ms"); } }
/** * Retains only the elements in this list that are contained in the * specified collection. In other words, removes from this list all * of its elements that are not contained in the specified collection. * * @param c collection containing elements to be retained in this list * @return {@code true} if this list changed as a result of the call * @throws ClassCastException if the class of an element of this list * is incompatible with the specified collection * (<a href="Collection.html#optional-restrictions">optional</a>) * @throws NullPointerException if this list contains a null element and the * specified collection does not permit null elements * (<a href="Collection.html#optional-restrictions">optional</a>), * or if the specified collection is null * @see Collection#contains(Object) */ public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, true); }
解读:取两个集合的交集