1、List集合
List继承了Collection,是有序的列表.
主要实现类有ArrayList、LinkedList、Vector、Stack等
ArrayList :
- 数组队列,非线程安全。被始化为Object[],查询修改快、增加删除慢,允许null值
- 动态扩容,初始10,扩容size的1.5倍 newCapacity = size + (size >> 1),阈值Integer.MAX_VALUE
- 删除会发生数据元素的移动,通过System.arraycopy数据拷贝实现
- modCount:迭代器通过modCount的值保持一致
- transient :表示序列化时被忽视。elementData扩容的过程中是可变的,ArrayList才会在elementData属性前加上transient修饰符,序列化是通过流的方式实现ArrayList的writeObject()、readObject():
LinkedList :
- 链表实现(1.8单向链表),非线程安全
- 查询更新慢、增加删除快(查询采为2分法迭代)
Node<E> node(int index) {
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
Vector :
- 数组实现、线程安全的。synchronized方式实现的线程安全数组
- 动态扩容,初始10。扩容是1倍。空构造会初始化一个容量为10的数组,不像ArrayList是空的不可变数组。
Stack :
- 基于数组实现的栈,线程安全它继承与Vector,特性是FILO(先进后出)
- Stack也是通过数组实现的,而非链表
CopyOnWriteArrayList :
- concurrent并发包中ArrayList线程安全的新实现方式
- Lock方式实现的线程安全。
2、Set集合
继承了Collection,值无序不可重复。 主要实现类有
HashSet、Hashtable、TreeSet、LinkedHashSet等
HashSet:
- 通过HashMap Key的特性实现的不可重复的无序集合。允许null值
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
TreeSet:
- TreeSet也是基于TreeMap来实现有序不可重的集合;允许插入Null值;非线程安全;
- 自然排序、自定义排序,默认是自然排序;
- 底层使用红黑树结构,而不是哈希表结构;
- TreeSet实现NavigableSet接口使得TreeSet具备了元素搜索功能;
LinkedHashSet:
- LinkedHashSet也是基本LinkedHashMap实现的有序不可重复的集合、非线程安全
- 数据结构是链表和哈希表,元素有序唯一
CopyOnWriteArraySet:
- concurrent并发包中set线程安全类
- CopyOnWriteArraySet是通过CopyOnWriteArrayList 实现,插入元素先判断是否存在
- Lock方式实现的线程安全。
/**
* Appends the element, if not present.
*
* @param e element to be added to this list, if absent
* @return {@code true} if the element was added
*/
public boolean addIfAbsent(E e) {
Object[] snapshot = getArray();
return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
addIfAbsent(e, snapshot);
}
3、Map集合
Map 是不同于Collection的一种键-值对(key-value)集合,
主要实现类有HashMap、LinkedHashMap、TreeMap、HashTable等。
HashMap:
- HashMap由数组+链表实现的key-value键值对集合,无序不可重复、非线程安全
// Hash表初始容量 16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
//数组最大容量 1073741824
static final int MAXIMUM_CAPACITY = 1 << 30;
//默认加载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
static class Node<K,V> implements Map.Entry<K,V> {
final int hash; //key hashCode取模运算后在数组中对应的index下标
final K key; //数据的key
V value; //数据的value
Node<K,V> next; //指向下一个节点
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//put方法懒加载实现
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
- 单向链表,最后一个链表节点entry的next指向null
并允许使用 null 值和 null 键 - HashMap 通过 (n - 1) & hash 来决定元素的位置(n 是当前数组大小)
- Node[] table:存储数据的哈希表;初始长度 length = 16,扩容时容量为原先的两倍(n * 2)
- loadFactor:负载因子,确定数组长度与当前所能存储的键值对最大值的关系;
- threshold:所能容纳的 key-value 对极限 ;threshold = length * Load factor,当存在的键值对大于该值,则进行扩容
- 懒加载:new Hash()未初始化哈希表 Node[] table;当发现哈希表为空或者长度为 0 时,会使用 resize 方法进行初始化,这里很显然运用了 lazy-load 懒加载原则,当哈希表被首次使用时,才进行初始化。
当链表中元素大于等于 8,这时有可能将链表改造为红黑树的数据结构,为什么我这里说可能呢?
static final int TREEIFY_THRESHOLD = 8;//默认链表元素大于等于8可被树化
static final int MIN_TREEIFY_CAPACITY = 64; //可树化的最小表容量为 64,
//putVal method
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e;
//哈希表容量<64,继续扩容而不树化
//防止哈希表容量较小,哈希碰撞的几率会比较大,导致出现长链表
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize();
else if ((e = tab[index = (n - 1) & hash]) != null) {
//todo 这里转化红黑树
}
}
TreeMap :
- 红黑树的实现 一种键-值对(key-value)可排序集合,非线程安全。
- TreeMap集合是基于红黑树(Red-Black tree)
- NavigableMap实现
- TreeMap保存的记录会根据 Key 排序(默认为升序排序), key 必须实现 Comparable 接口,可自定义排序。
- TreeMap 会按照其 key 的 compareTo 方法来判断 key 是否重复
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:
- 一个遗留类,线程安全,与 HashMap 类似
- 当不需要线程安全时,选择 HashMap 代替
- 当需要线程安全时,使用 ConcurrentHashMap 代替
本文详细总结了Java集合框架中的List、Set和Map集合。List包括ArrayList、LinkedList、Vector和Stack的特点与实现原理。Set部分讲解了HashSet、TreeSet和LinkedHashSet,强调了它们的无序性和唯一性。Map部分则涵盖了HashMap、LinkedHashMap、TreeMap和Hashtable,分析了它们的存储结构和性能特点,特别是HashMap的扩容策略和TreeMap的红黑树实现。
1901

被折叠的 条评论
为什么被折叠?



