List
- ArrayList:
- 使用数组实现,查询快,增删慢,非线程安全
- 默认长度是0,添加元素时判断如果是初始共享数组,则扩容长度10,固定1.5倍扩容
- 按插入顺序排序,可重复元素
/* 添加元素时如果是共享实例数组则扩容长度为10 */
private static final int DEFAULT_CAPACITY = 10;
/* 与下面一样,区分的目的在于了解第一次数组添加元素时数组的扩容状况 */
private static final Object[] EMPTY_ELEMENTDATA = {};
/* 用于共享空实例数组,防止多次创建空数组浪费系统资源 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/* ArrayList使用该数组存储数据 */
transient Object[] elementData;
/* 创建并赋值空数组 */
public ArrayList() {
/* 注意:当前是空数组,默认长度是0 */
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public boolean add(E e) {
/* 判断长度,根据条件扩容 */
ensureCapacityInternal(size + 1); // Increments modCount!!
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;
/* 1.5倍扩容 */
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
- LinkedList:
- 使用双向链表(Node<E>)实现,查询慢,增删快,非线程安全
transient Node<E> first;
transient Node<E> last;
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
/* 省略 */
}
- Vector:
- 使用数组实现,查询快,增删慢,使用了synchronized对象锁,线程安全
- 默认长度为10,扩容时如果扩容量大于0当前长度加扩容量,否则扩容量加扩容量
- 按插入顺序排序,可重复元素
/* 使用数组存储数据 */
protected Object[] elementData;
/* 容器扩容时增长量 */
protected int capacityIncrement;
public Vector() {
this(10);
}
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
private void ensureCapacityHelper(int minCapacity) {
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
/* 根据增长量设置扩容,默认增长量0,每次扩容时容量翻倍 */
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);
}
Map
- HashMap:
- 使用单向链表(Node<K,V>)数组实现,非线程安全
- 数组长度默认16,链表长度超出8会转换成红黑树
- 最多仅允许一条Key为null,"null"可以和null同时存在
- 根据Key的哈希值确定当前元素存储到的数组位置,以数组排序
/* 无参构造器创建容器首次添加元素会自动初始化容器为2的4次幂 16 */
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
/* 有参构造器创建容器参数大于该值则替换 */
static final int MAXIMUM_CAPACITY = 1 << 30;
/* 默认负载因子,当存储量超出负载因子时进行扩容 */
static final float DEFAULT_LOAD_FACTOR = 0.75f;
/* 链表阈值,数组节点的链表节点超出该值会转换为红黑树 */
static final int TREEIFY_THRESHOLD = 8;
/* 数据容器 */
transient Node<K,V>[] table;
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
/* 单向链表节点 */
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
/* 省略 */
}
/* 红黑树节点 */
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
TreeNode<K,V> parent; // red-black tree links
TreeNode<K,V> left;
TreeNode<K,V> right;
TreeNode<K,V> prev; // needed to unlink next upon deletion
boolean red;
/* 省略 */
}
- LinkedHashMap:
- 使用双向链表(Entry<K,V>)数组实现,非线程安全
- 为有序(添加顺序排序)且不可重复
- 继承自HashMap并重写了newNode方法,在创建节点时返回双向链表节点
- 因为继承自HashMap所以数组容器长度默认为16,Key值可以为null
/* 双向链表首节点 */
transient LinkedHashMap.Entry<K,V> head;
/* 双向链表尾节点 */
transient LinkedHashMap.Entry<K,V> tail;
/* 访问顺序为true,对于插入顺序为false */
final boolean accessOrder;
public LinkedHashMap() {
super();
accessOrder = false;
}
/* 重写HashMap的newNode方法,返回双向链表节点 */
Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
LinkedHashMap.Entry<K,V> p = new LinkedHashMap.Entry<K,V>(hash, key, value, e);
linkNodeLast(p);
return p;
}
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
- TreeMap:
- 使用红黑树(Entry<K,V>节点)实现,非线程安全
- 可以对添加进来的元素进行自动排序,默认使用自然顺序排序
- Key值不能是null,否则会报空指针异常
/* 比较器用于维护树映射中的顺序,如果使用键的自然顺序则为null,默认null */
private final Comparator<? super K> comparator;
/* 红黑树根节点 */
private transient Entry<K,V> root;
public TreeMap() {
comparator = null;
}
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
static final class Entry<K,V> implements Map.Entry<K,V> {
K key;
V value;
Entry<K,V> left;
Entry<K,V> right;
Entry<K,V> parent;
boolean color = BLACK;
/* 省略 */
}
- HashTable:
- 使用单向链表(Entry<K,V>)数组实现,使用了synchronized对象锁,线程安全
- 容器大小默认11,负载因子0.75,数组扩容时直接翻倍加一,第一次扩容变为23
- Key值不能是null,否则会报空指针异常
/* 单向链表数组 */
private transient Entry<?,?>[] table;
public Hashtable() {
this(11, 0.75f);
}
public Hashtable(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal Load: "+loadFactor);
if (initialCapacity==0)
initialCapacity = 1;
this.loadFactor = loadFactor;
table = new Entry<?,?>[initialCapacity];
threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
}
public synchronized V put(K key, V value) {
if (value == null) {
throw new NullPointerException();
}
Entry<?,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
addEntry(hash, key, value, index);
return null;
}
private void addEntry(int hash, K key, V value, int index) {
modCount++;
Entry<?,?> tab[] = table;
if (count >= threshold) {
rehash();
tab = table;
hash = key.hashCode();
index = (hash & 0x7FFFFFFF) % tab.length;
}
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>) tab[index];
tab[index] = new Entry<>(hash, key, value, e);
count++;
}
private static class Entry<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Entry<K,V> next;
/* 省略 */
}
- ConcurrentHashMap:
- 使用单向链表数组实现,使用了synchronized代码块锁,锁住的是数组节点中的单向链表,效率更高,线程安全
- 默认初始容量16,负载因子0.75,链表阈值8超出阈值转换成红黑树
private static final int MAXIMUM_CAPACITY = 1 << 30;
private static final int DEFAULT_CAPACITY = 16;
private static final float LOAD_FACTOR = 0.75f;
static final int TREEIFY_THRESHOLD = 8;
static final int UNTREEIFY_THRESHOLD = 6;
transient volatile Node<K,V>[] table;
private transient volatile Node<K,V>[] nextTable;
Set
- HashSet:底层以HashMap的Key值实现数据存储,所有对应Value都是new Object(),有序(Key值的Hash值排序)不可重复集,非线程安全
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
- LinkedHashSet:底层以LinkedHashMap的Key值实现数据存储,所有对应Value都是new Object(),有序(添加顺序排序)不可重复集,非线程安全
public LinkedHashSet() {
super(16, .75f, true);
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
- TreeSet:底层默认以TreeMap的Key值实现数据存储,所有对应Value都是new Object(),可以对添加进来的元素进行排序,非线程安全
private transient NavigableMap<E,Object> m;
private static final Object PRESENT = new Object();
public TreeSet() {
this(new TreeMap<E,Object>());
}
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
Collection:是List和Set集合的父类,是一个集合接口,提供了对集合对象进行基本操作的通用方法
Collections:是一个工具类,不能被实例化,提供了很多集合功能
Comparable :内比较器,使用compareTo(T o)方法对当前类与参数进行比较
Comparator:外比较器,使用compare(T o1, T o2)方法对传入的参数进行比较