集合不安全
PPG007 ... 2021-12-28 About 2 min
# 集合不安全
# List 不安全
解决方案:
Vector:
Vector<String> strings = new Vector<>();
1Vector 的 add 方法安全的原因:
使用了synchronized关键字。
public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; }
1
2
3
4
5
6Collections.synchronizedList:
List<Object> objects = Collections.synchronizedList(new ArrayList<>());
1CopyOnWriteArrayList写入时复制:
CopyOnWriteArrayList<String> strings = new CopyOnWriteArrayList<>();
1
# Set 不安全
解决方案:
Collections.synchronizedSet:
Set<Object> objects = Collections.synchronizedSet(new HashSet<>());
1CopyOnWriteArraySet:
CopyOnWriteArraySet<String> strings = new CopyOnWriteArraySet<>();
1
Tips
HashSet 通过 HashMap 的键确保不会重复:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
1
2
3
2
3
# Map 不安全
# HashMap 的扩容机制和加载因子
默认加载因子、默认初始容量、最大容量:
public class HashMap<K,V>extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable{
// 默认的初始容量(容量为HashMap中桶的数目)是16,且实际容量必须是2的整数次幂。
static final int DEFAULT_INITIAL_CAPACITY = 16;
// 最大容量(必须是2的幂且小于2的30次方,传入容量过大将被这个值替换)
static final int MAXIMUM_CAPACITY = 1 << 30;
// 默认加载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//... 省略
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
最大容量等于默认加载因子和初始容量的乘积,是用来预警的,如果 HashMap 中的容量超过这个阀值了,那就会执行扩容操作,低于则没事。
加载因子存在的原因,还是因为减缓哈希冲突,如果初始桶为 16,等到满 16 个元素才扩容,某些桶里可能就有不止一个元素了。所以加载因子默认为 0.75,也就是说大小为 16 的 HashMap,到了第 13 个元素,就会扩容成 32。
所以如果你心目中有明确的 Map 大小,设定时一定要考虑加载因子的存在。
扩容阈值就是初始桶大小(默认 16)乘以加载因子
HashMap 含参构造器:
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12