List
有序集合,允许重复的元素,允许插入多个null元素,根据元素的索引访问元素
ArrayList
底层数组实现,无参构造器默认实现容量为10的空数组
查找直接由位置索引
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
无索引位置直接插入,指定位置插入存在数组复制
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
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; // clear to let GC do its work
return oldValue;
}
ArrayList扩容,数组大小超过设定容量时自动扩容至1.5倍大小
private void grow(int minCapacity) {
// overflow-conscious code
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);
// minCapacity is usually close to size, so this is a win:
//System.arraycopy针对已存在的源数组和目的数组进行拷贝,Arrays.copyOf拷贝需创建新的目的数组,底层调用System.arraycopy
elementData = Arrays.copyOf(elementData, newCapacity);
}
LinkedList
底层为双向链表实现
Vector
Stack
Set
不包含重复元素的集合,最多包含一个null元素
HashSet
特性:
- 基于HashMap实现,无序容器,侧重在存储数据的唯一性
- 允许存在null值
- 非线程安全实现
- HashSet迭代遵循fail-fast机制
类成员变量,插入元素作为map的key对象,value对象保持不变为Object
private transient HashMap map;
private static final Object PRESENT = new Object();
无参构造函数
public HashSet() {
map = new HashMap<>();
}
HashSet查找,插入,删除操作均借助HashMap实现
public boolean contains(Object o) {
return map.containsKey(o);
}
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public boolean contains(Object o) {
return map.containsKey(o);
}
LinkedHashSet
特点:
- 继承于HashSet,基于LinkedHashMap实现
- 有序容器,由LinkedHashMap实现迭代顺序于元素插入顺序一致
- 非线程安全实现
- LinkedHashSet迭代遵循fail-fast机制
//无参数构造函数默认调用HashSet构造函数
public LinkedHashSet() {
super(16, .75f, true);
}
此构造函数使用LinkedHashMap实现,保证元素FIFO
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
TreeSet
特点:
- 基于TreeMap实现,由TreeMap保证有序
- 增删查操作时间复杂度为log(n)
- 非线程安全
- 迭代遵循fail-fast机制
- 不允许null值对象
成员变量,TreeSet内部基于TreeMap实现
private transient NavigableMap m;
//值对象固定为Object
private static final Object PRESENT = new Object();
//无参构造器
public TreeSet() {
this(new TreeMap());
}
迭代器:
//升序迭代器
public Iterator iterator() {
return m.navigableKeySet().iterator();
}
//降序迭代器
public Iterator descendingIterator() {
return m.descendingKeySet().iterator();
}
Map
Map并非collection的子接口或者实现类,每个Entry都持有两个对象,键对象和值对象,Map可能会持有相同的值对象但键对象唯一
HashMap
特性:
- 非线程安全
- 键对象允许1个null值,值对象允许多个null值
- 父类是AbstractMap
- 无序容器
HashTable
特性:
- 不允许null值
- 线程安全
- Hashtable的父类是Dictionary
- 无序容器
LinkedHashMap
特性:
- 非线程安全
- 有序容器,内部维护链接全部Entry双向指针实现迭代顺序与Entry插入顺序一致
LinkedHashMap的Node继承于HashMap的Node同时增加头尾指针:
static class Entry extends HashMap.Node {
Entry before, after;
Entry(int hash, K key, V value, Node next) {
super(hash, key, value, next);
}
}
TreeMap
特性:
- 基于红黑树实现
- 有序容器,由key对象类实现Comparable接口或者是比较器Comparator实现排序
- 增删查改时间复杂度为log(n)
- 非线程安全实现
TreeMap的put方法
public V put(K key, V value) {
Entry 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 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 e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
其中compare方法
final int compare(Object k1, Object k2) {
//comparator为TreeMap的成员变量
return comparator==null ? ((Comparable super K>)k1).compareTo((K)k2)
: comparator.compare((K)k1, (K)k2);
}
- 基本数据类型包装类,String类等默认实现Comparable接口,可直接作为key对象
-
自定义对象:
- 实现Comparable接口,重写Compareto方法
- 自定义比较器类,并且要让其实现Comparator接口,通过以下构造方法指定使用自定义比较器类
集合类线程安全实现
- 线程安全包装类
Set s = Collections.synchronizedSet(new HashSet(...));
SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));
SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));
fail-fast机制
即快速失败机制,它是Java集合的一种错误检测机制。当多个线程对集合进行结构上的改变的操作时,此时程序会抛出 ConcurrentModificationException异常,从而产生fail-fast机制。
//如在ArrayList内部实现的迭代器中,当调用方法next或者remove时会首先检查modCount == expectedModCount(创建迭代器时由modCount赋值)
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}