总结:List集合

总结: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的最大值,否则指定为限制容量大小。然后通过数组的复制将原数据复制到一个更大(新的容量大小)的数组。