关于HashSet和HashMap
HashSet是用HashMap实现的,HashSet的构造方法。
public HashSet() {
map = new HashMap<E,Object>();
}
HashSet的add()方法
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
可以看到所有的add,只是把要添加的对象放进了map的key的位置,value的位置都放进了同一个对象。
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
在map或者set中进行添加的实际代码
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
如果两个key的hash值相同并且两个key的==或者equals成立则认为这是两个相同的key,添加值时采用覆盖旧值的方法。
关于HashMap的大小。
transient Entry[] table;这个数组的长度总是2的幂次。
// Find a power of 2 >= initialCapacity
int capacity = 1;
while (capacity < initialCapacity)
capacity <<= 1;
因为这样计算index的时候比较快
static int indexFor(int h, int length) {
return h & (length-1);
}
因为length是2的幂次,所以length-1就是0111...,与运算就是求余运算。
关于键值key==null的存放位置
Note: Null keys always map to hash 0, thus index 0.
存放在table[0]的位置
关于ConcurrentHashMap
Retrieval operations (including <tt>get</tt>) generally do not block, so may overlap with update operations (including
* <tt>put</tt> and <tt>remove</tt>).
查询操作并不会阻塞,所以它有可能跟更新操作冲突。
The allowed concurrency among update operations is guided by the optional <tt>concurrencyLevel</tt> constructor argument
(default <tt>16</tt>), which is used as a hint for internal sizing.
在更新操作时允许的并发数由变量concurrencyLevel设定。
关于java.util.concurrent.atomic 包
类的小工具包,支持在单个变量上解除锁的线程安全编程。有:
AtomicInteger
AtomicBoolean
AtomicIntegerArray
AtomicReference<V>等
Java的CAS会使用现代处理器上提供的高效机器级别原子指令,这些原子指令以原子方式对内存执行读-改-写操作,这是在多处理器中实现同步的关键。concurrent包中大多数类都是使用了java的CAS作为基础来实现的。