1.  Collection 接口

// Collection 接口在其源码中的定义:
 * 1. Collection 是集合层次结构中的根接口
 * 2. 一个 Collection 代表 一组对象(objects),这些对象称为其元素(elements)
 * 3. 一些 Collection 允许有重复的元素,而另一些 Collection 不允许有重复的元素
 * 4. 一些 Collection 的元素是有序的,而另一些 Collection 是无序的
 * 5. JDK 没有提供任何直接(direct)实现 Collection 的类
 * 6. JDK 只提供了继承 Collection 的“子接口”(List 和 Set)的实现类

 * -Set 中的元素没有顺序且不可以重复
 * -List 中的元素有顺序且可以重复
 * -Map 接口定义了存储 “键(key)- 值(value)映射对” 的方法,键(key)不能重复,重写 hashCode() 和 equals() 方法!
 * 
 *      * 接口             Collection
 *                        /        \
 *      * 接口           Set        List               Map
 *                       |        /     \              |
 *      * 类         HashSet  ArrayList LinkedList    HashMap

// 谈到 Collection 接口,我们不得不区别一下 Collections 类
// Collections 是一个类,不能实例化,是一个工具类,它包含各种有关集合操作的静态(static)多态方法,比如 sort、search、shuffle 以及线程安全等操作
public class Collections {
    // 私有化构造器,所以不能被实例化
    private Collections() {
    }
    ...
}

 

2.  ArrayList

1. ArrayList 是 List 接口的实现类,并继承于 AbstractList(AbstractList 继承于 AbstractCollection,并且实现了大部分 List 接口)
2. ArrayList 的底层实现是动态数组(属于数据结构中的可扩容的线性表),线程不安全,效率高

// 创建
List list = new ArrayList();

// 常用方法
list.size();// 返回元素的数量
list.isEmpty();
list.add(element);
list.add(index, element);// 在指定位置添加元素
list.remove(index);// 删除指定索引的元素,并返回该元素内容
list.remove(element);// 删除指定元素,删除成功返回 true
list.get(index);// 获取指定位置的元素
list.toArray();// 返回一个包含列表中的所有元素的数组
list.contains(element);// 判断是否包含指定元素
list.indexOf(element);// 返回指定元素所在的第一个位置,没找到返回 -1
list.lastIndexOf(element);// 返回指定元素所在的最后一个位置
list.clear();// 删除所有元素

// 为了更深入了解 ArrayList,我们来分析一下 ArrayList 的部分源码  
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final int DEFAULT_CAPACITY = 10;// 默认容量为 10
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;// 最大容量
    private static final Object[] EMPTY_ELEMENTDATA = {};
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    transient Object[] elementData;// 可见底层是 Object 对象数组
    private int size;// 包含元素的数量

    // 无参构造器,对象数组默认为空
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    // 有参构造器,用于初始化数组容量
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
        }
    }

    // 返回所包含元素的数量
    public int size() {
        return size;
    }

    // 判断对象数组是否为空
    public boolean isEmpty() {
        return size == 0;
    }

    // 返回一个包含列表中的所有元素的数组
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }
    
    // 删除元素
    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);
        elementData[--size] = null;
        return oldValue;
    }

    // 添加元素
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);// 判断是否需要扩容
        elementData[size++] = e;
        return true;
    }

    // 判断是否需要扩容
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        ensureExplicitCapacity(minCapacity);
    }
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    // 扩容方法
    private void grow(int minCapacity) {
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        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)
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
    }
    ...
 } 
ArrayList

相关文章: