List集合
ArrayList、LinkedList、Vector这三个集合都实现了List集合接口,是有序集合,可以存储重复元素。
ArrayList集合
List集合是有序的,可以存放重复的元素,底层是通过一个动态数组来实现,默认长度为10,通过group方法扩容,每次扩容1.5倍。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
private void grow(int minCapacity) {
// overflow-conscious code
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);
}
ArrayList接口实现了List集合,具有List集合的所有功能。实现了RandomAccess接口(随机访问),这个接口没有方法体,只是一个标记的作用,说明ArrayList集合的随机访问效率较高,因为ArrayList的底层是通过一个动态数组实现的,在访问的时候,可以直接通过索引获取对应的元素,但是在随机增删的时候效率较低,因为数组在内存中是连续的,在增删元素的时候,会判断容量是否够用,如果容量不足,会先扩容数组,其它位置的元素会相应的前移后移。
LinkedList集合
LinkedList集合是有序的,可以存放重复的元素,底层是通过一个双向链表来实现。
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
transient Node<E> first;
transient Node<E> last;
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
LinkedList实现了Deque,即双端队列,支持在两端插入元素。LinkedList集合是通过双向链表实现的,所以该集合随机增删的速度较快,因为链表在内存中是不连续存在的,只需要在增删的时候改变指针指向的结点就可以了;但是随机查询的速度较慢,在使用get()方法查询时,会先判断该参数是否在链表中间位置之前或之后,然后在从头部向尾部或从尾部向头部依次查询,这样依次遍历就导致查询效率较低,在进行大量数据遍历的时通常使用迭代器遍历,会极大的提高查询速度。
Vector集合
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
Vector集合在底层也是通过数组实现的,调用构造方法时的默认长度为10,通过grow方法实现扩容机制,每次的长度为原来的两倍,该集合的方法被synchronized关键字修饰,所以是线程安全的,但是效率有所降低。所以在单线程访问操作集合时,使用ArrayList集合,在多线程操作集合的时候使用Vector集合。
protected Object[] elementData;
public Vector() {this(10);}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
public synchronized boolean isEmpty() {
return elementCount == 0;
}
public synchronized void insertElementAt(E obj, int index) {
modCount++;
if (index > elementCount) {
throw new ArrayIndexOutOfBoundsException(index
+ " > " + elementCount);
}
ensureCapacityHelper(elementCount + 1);
System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
elementData[index] = obj;
elementCount++;
}
Set集合
public interface Set<E> extends Collection<E>
Set集合继承了Collection集合,Set的底层是通过红黑树实现的,不能存储重复元素,并且存储的元素也是无序的,Set集合没有索引,无法使用普通的for循环遍历。
HashSet
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
实现了set集合,不能存储重复的元素,元素无序,底层是基于哈希表实现的。
public HashSet() {
map = new HashMap<>();
}
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}