总结:List集合
复制一个List集合:
public class Test2{ public static void main(String[] args){ List list = new ArrayList() ; list.add(3) ; list.add(6) ; list.add(1) ; list.add(2) ; list.add(100) ; list.add(5) ; List list2 = new ArrayList(list.size()) ; list2.addAll(list) ; System.out.println("===========>"); System.out.println("原List"+list); System.out.println("复制List"+list2); List list3 = new ArrayList(list.size()) ; Collections.copy(list3,list); System.out.println("复制的list"+list3); } }
总结:复制一个list,可以用“目标list.addAll(要复制的list)” ;
使用Collections.copy(目标list,原list) ;会有数组下标越界报错。
list集合排序:
public class Test3 { public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>() ; list.add(3) ; list.add(6) ; list.add(1) ; list.add(2) ; list.add(100) ; list.add(5) ; Collections.sort(list); System.out.println(" Collections.sort从小到大排序结果"+list); Collections.reverse(list); System.out.println(" Collections.sort从大到小排序结果"+list); list.sort(Comparator.naturalOrder()); System.out.println(" list.sort从小到大排序结果"+list); list.sort(Comparator.reverseOrder()); System.out.println(" list.sort从大到小排序结果"+list); } }
ArrayList的扩容机制:
概述:ArrayList是List接口的实现,它是支持根据需要而动态增长的数组。java中标准数组是定长的,在数组被创建之后,他们不能被加长或者缩短。这就意味着在创建数组时需要知道数组的所需长度,但有时我们需要动态程序中获取数组长度。ArrayList就是为此而生的。
ArrayList的扩容机制
扩容发生在add()方法调用的时候。
/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return <tt>true</tt> (as specified by {@link Collection#add}) */ public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
说明:代码中ensureCapacityInternal()方法是用来扩容的,传入的形式参数为“最小扩容量”
private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); }
private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return 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 //===1获取ArrayList中元素数据的内存长度。确定它当前的容量大小 int oldCapacity = elementData.length; //===2扩容为当前容量的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); //===3判断扩容后的数组的容量够不够,如果够了就直接使用这个长度创建数组,如果不够就将数组长度设置为需要的长度。 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //===4如果预设的数组容量值大于默认的最大值 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: //调用Arrays.copyOf()方法将elementData数组指向新的内存空间是newCapacity的连续空间。并且将elementData数据元素复制给新数组 elementData = Arrays.copyOf(elementData, newCapacity); }
说明:
(1)在calculateCapacity()方法中,如果传入的是一个空数组则最小容量取默认容量与minCapatity参数之间的最大值。”
(2)而ensureExplicitCapacity()方法,用来判断是否需要扩容,该方法中如果最小需要空间比elementData的内存空间大,则需要扩容
(3)grow()方法是扩容的核心方法
ArrayList扩容的本质:就算出新的扩容数组的size后实例化,并将原有数组内容复制到新数组中去。 总之,再通俗一点ArrayList的默认容量是10,如果初始化的时候就指定了容量或者放入了一个指定的集合参数,那么容量的大小就是这个指定的大小或者是放入的这个集合的size。每次扩容为原来的1.5倍。如果新增后超过这个容量,则容量为新增后所需的最小容量。如果增加0.5倍后的新容量超过限制的容量,则用所需的最小容量与限制的容量进行判断,超过则指定为Integer的最大值,否则指定为限制容量大小。然后通过数组的复制将原数据复制到一个更大(新的容量大小)的数组。