ConcurrentHashMap

林炳文Evankaka原创作品。转载请注明出处http://blog.****.net/evankaka

       摘要:本文主要讲了Java中ConcurrentHashMap 的源码

       ConcurrentHashMap 是java并发包中非常有用的一个类,在高并发场景用得非常多,它是线程安全的。要注意到虽然HashTable虽然也是线程安全的,但是它的性能在高并发场景下完全比不上ConcurrentHashMap ,这也是由它们的结构所决定的,可以认为ConcurrentHashMap 是HashTable的加强版,不过这加强版和原来的HashTable有非常大的区别,不仅是在结构上,而且在方法上也有差别。

         下面先来简单说说它们的区别吧HashMap、 HashTable、ConcurrentHashMap 的区别吧

1、HashMap是非线程安全,HashTable、ConcurrentHashMap 都是线程安全,而且ConcurrentHashMap 、Hashtable不能传入nul的key或value,HashMap可以。

2、Hashtable是将数据放入到一个Entrty数组或者它Entrty数组上一个Entrty的链表节点。而ConcurrentHashMap 是由Segment数组组成,每一个Segment可以看成是一个单独的Map.然后每个Segment里又有一个HashEntrty数组用来存放数据。

3、HashTable的get/put/remove方法都是基于同步的synchronized方法,而ConcurrentHashMap 是基本锁的机制,并且每次不是锁全表,而是锁单独的一个Segment。所以ConcurrentHashMap 的性能比HashTable好。

4、如果不考虑线程安全因素,推荐使用HashMap,因为它性能最好。

 

首先来看看它包含的结构吧!

 

 
  1. public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>

  2. implements ConcurrentMap<K, V>, Serializable {

  3. private static final long serialVersionUID = 7249069246763182397L;

  4.  
  5. //默认数组容量大小

  6. static final int DEFAULT_INITIAL_CAPACITY = 16;

  7.  
  8. //默认装载因子

  9. static final float DEFAULT_LOAD_FACTOR = 0.75f;

  10.  
  11. //默认层级

  12. static final int DEFAULT_CONCURRENCY_LEVEL = 16;

  13.  
  14. //最大的每一个数组容量大小

  15. static final int MAXIMUM_CAPACITY = 1 << 30;

  16.  
  17. //最大的分组数目

  18. static final int MAX_SEGMENTS = 1 << 16; // slightly conservative

  19.  
  20. //调用remove/contain/replace方法时不加锁的情况下操作重试次数

  21. static final int RETRIES_BEFORE_LOCK = 2;

  22.  
  23. //segments 数组索引相关

  24. final int segmentMask;

  25.  
  26. //segments 数组偏移相关

  27. final int segmentShift;

  28.  
  29. //segments数组,每个segments单独就可以认为是一个map

  30. final Segment<K,V>[] segments;

这里看到了一个Segment<K,V>[] segments;数组。下面再来看看Segment这个类。在下面可以看到Segment这个类继承了ReentrantLock锁。所以它也是一个锁。然后它里面还有一个HashEntry<K,V>[] table。这是真正用来存放数据的结构。

 

 

 
  1. /**

  2. * Segment内部类,注意它也是一个锁!可以认为它是一个带有锁方法的map

  3. */

  4. static final class Segment<K,V> extends ReentrantLock implements Serializable {

  5.  
  6. private static final long serialVersionUID = 2249069246763182397L;

  7.  
  8. //元素个数

  9. transient volatile int count;

  10. //修改次数

  11. transient int modCount;

  12. //阈值,超过这个数会重新reSize

  13. transient int threshold;

  14. //注意,这里又一个数组,这个是真正存放数据元素的地方

  15. transient volatile HashEntry<K,V>[] table;

  16. //装载因子,用来计算threshold

  17. final float loadFactor;


HashEntry它的结构很简单:

 

 

 
  1. static final class HashEntry<K,V> {

  2. final K key;

  3. final int hash;//用来保存Segment索引的信息

  4. volatile V value;

  5. final HashEntry<K,V> next;

  6.  
  7. HashEntry(K key, int hash, HashEntry<K,V> next, V value) {

  8. this.key = key;

  9. this.hash = hash;

  10. this.next = next;

  11. this.value = value;

  12. }

  13.  
  14. @SuppressWarnings("unchecked")

  15. static final <K,V> HashEntry<K,V>[] newArray(int i) {

  16. return new HashEntry[i];

  17. }

  18. }


经过上面的分析:可以得出如下的ConcurrentHashMap结构图

 

ConcurrentHashMap

全部源码分析:

 

 
  1. package java.util.concurrent;

  2. import java.util.concurrent.locks.*;

  3. import java.util.*;

  4. import java.io.Serializable;

  5. import java.io.IOException;

  6. import java.io.ObjectInputStream;

  7. import java.io.ObjectOutputStream;

  8.  
  9. public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>

  10. implements ConcurrentMap<K, V>, Serializable {

  11. private static final long serialVersionUID = 7249069246763182397L;

  12.  
  13. //默认数组容量大小

  14. static final int DEFAULT_INITIAL_CAPACITY = 16;

  15.  
  16. //默认装载因子

  17. static final float DEFAULT_LOAD_FACTOR = 0.75f;

  18.  
  19. //默认层级

  20. static final int DEFAULT_CONCURRENCY_LEVEL = 16;

  21.  
  22. //最大的每一个数组容量大小

  23. static final int MAXIMUM_CAPACITY = 1 << 30;

  24.  
  25. //最大的分组数目

  26. static final int MAX_SEGMENTS = 1 << 16; // slightly conservative

  27.  
  28. //调用remove/contain/replace方法时不加锁的情况下操作重试次数

  29. static final int RETRIES_BEFORE_LOCK = 2;

  30.  
  31. //segments 数组索引相关

  32. final int segmentMask;

  33.  
  34. //segments 数组偏移相关

  35. final int segmentShift;

  36.  
  37. //segments数组,每个segments单独就可以认为是一个map

  38. final Segment<K,V>[] segments;

  39.  
  40. /**

  41. * 哈希算法

  42. */

  43. private static int hash(int h) {

  44. // Spread bits to regularize both segment and index locations,

  45. // using variant of single-word Wang/Jenkins hash.

  46. h += (h << 15) ^ 0xffffcd7d;

  47. h ^= (h >>> 10);

  48. h += (h << 3);

  49. h ^= (h >>> 6);

  50. h += (h << 2) + (h << 14);

  51. return h ^ (h >>> 16);

  52. }

  53.  
  54. /**

  55. * 根据哈希值计算应该落在哪个segments上

  56. */

  57. final Segment<K,V> segmentFor(int hash) {

  58. return segments[(hash >>> segmentShift) & segmentMask];

  59. }

  60.  
  61.  
  62. /**

  63. * 内部类,每个HashEntry都会存入到一个Segment中去

  64. */

  65. static final class HashEntry<K,V> {

  66. final K key;//关键字

  67. final int hash;//哈希值

  68. volatile V value;//值

  69. final HashEntry<K,V> next;//不同的关键字,相再的哈希值时会组成 一个链表

  70.  
  71. HashEntry(K key, int hash, HashEntry<K,V> next, V value) {

  72. this.key = key;

  73. this.hash = hash;

  74. this.next = next;

  75. this.value = value;

  76. }

  77.  
  78. @SuppressWarnings("unchecked")

  79. static final <K,V> HashEntry<K,V>[] newArray(int i) {

  80. return new HashEntry[i];

  81. }

  82. }

  83.  
  84. /**

  85. * Segment内部类,注意它也是一个锁!可以认为它是一个带有锁方法的map

  86. */

  87. static final class Segment<K,V> extends ReentrantLock implements Serializable {

  88.  
  89. private static final long serialVersionUID = 2249069246763182397L;

  90.  
  91. //元素个数

  92. transient volatile int count;

  93. //修改次数

  94. transient int modCount;

  95. //阈值,超过这个数会重新reSize

  96. transient int threshold;

  97. //注意,这里又一个数组,这个是真正存放数据元素的地方

  98. transient volatile HashEntry<K,V>[] table;

  99. //装载因子,用来计算threshold

  100. final float loadFactor;

  101.  
  102. //构造函数,由initialCapacity确定table的大小

  103. Segment(int initialCapacity, float lf) {

  104. loadFactor = lf;

  105. setTable(HashEntry.<K,V>newArray(initialCapacity));

  106. }

  107.  
  108. @SuppressWarnings("unchecked")

  109. static final <K,V> Segment<K,V>[] newArray(int i) {

  110. return new Segment[i];

  111. }

  112.  
  113. //设置threshold、table

  114. void setTable(HashEntry<K,V>[] newTable) {

  115. threshold = (int)(newTable.length * loadFactor);//注意,当table的元素个数超过这个时,会触发reSize;

  116. table = newTable;

  117. }

  118.  
  119. //取得头一个

  120. HashEntry<K,V> getFirst(int hash) {

  121. HashEntry<K,V>[] tab = table;

  122. return tab[hash & (tab.length - 1)];

  123. }

  124.  
  125. //在加锁情况下读数据,注意这个类继续了锁的方法

  126. V readValueUnderLock(HashEntry<K,V> e) {

  127. lock();

  128. try {

  129. return e.value;

  130. } finally {

  131. unlock();

  132. }

  133. }

  134.  
  135.  
  136. //取元素

  137. V get(Object key, int hash) {

  138. if (count != 0) { //注意,没有加锁

  139. HashEntry<K,V> e = getFirst(hash);//取得头一个

  140. while (e != null) { //依次从table中取出元素判断

  141. if (e.hash == hash && key.equals(e.key)) { //hash和key同时相等才表示存在

  142. V v = e.value;

  143. if (v != null) //有可能在这里时,运行了删除元素导致为Null,一般发生比较少

  144. return v;

  145. return readValueUnderLock(e); // 重新在加锁情况下读数据

  146. }

  147. e = e.next;

  148. }

  149. }

  150. return null;

  151. }

  152. //是否包含一个元素

  153. boolean containsKey(Object key, int hash) {

  154. if (count != 0) { //

  155. HashEntry<K,V> e = getFirst(hash);

  156. while (e != null) {

  157. if (e.hash == hash && key.equals(e.key))

  158. return true;

  159. e = e.next;

  160. }

  161. }

  162. return false;

  163. }

  164. //是否包含一个元素

  165. boolean containsValue(Object value) {

  166. if (count != 0) { // read-volatile

  167. HashEntry<K,V>[] tab = table;

  168. int len = tab.length;

  169. for (int i = 0 ; i < len; i++) {

  170. for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) { //table数组循环读数

  171. V v = e.value;

  172. if (v == null) // recheck

  173. v = readValueUnderLock(e);

  174. if (value.equals(v))

  175. return true;

  176. }

  177. }

  178. }

  179. return false;

  180. }

  181. //替换时要加锁

  182. boolean replace(K key, int hash, V oldValue, V newValue) {

  183. lock();

  184. try {

  185. HashEntry<K,V> e = getFirst(hash);

  186. while (e != null && (e.hash != hash || !key.equals(e.key)))//hash和key要同时相等才表示是找到了这个元素

  187. e = e.next;

  188.  
  189. boolean replaced = false;

  190. if (e != null && oldValue.equals(e.value)) { //判断是否要进行替换

  191. replaced = true;

  192. e.value = newValue;

  193. }

  194. return replaced;

  195. } finally {

  196. unlock();

  197. }

  198. }

  199. //替换时要加锁

  200. V replace(K key, int hash, V newValue) {

  201. lock();

  202. try {

  203. HashEntry<K,V> e = getFirst(hash);

  204. while (e != null && (e.hash != hash || !key.equals(e.key)))

  205. e = e.next;

  206.  
  207. V oldValue = null;

  208. if (e != null) {

  209. oldValue = e.value;

  210. e.value = newValue;

  211. }

  212. return oldValue;

  213. } finally {

  214. unlock();

  215. }

  216. }

  217.  
  218. //放入一个元素,onlyIfAbsent如果有false表示替换原来的旧值

  219. V put(K key, int hash, V value, boolean onlyIfAbsent) {

  220. lock();

  221. try {

  222. int c = count;

  223. if (c++ > threshold) // table数组里的元素超过threshold。触发rehash,其实也就是扩大table

  224. rehash();

  225. HashEntry<K,V>[] tab = table;

  226. int index = hash & (tab.length - 1);

  227. HashEntry<K,V> first = tab[index];//头一个

  228. HashEntry<K,V> e = first;

  229. while (e != null && (e.hash != hash || !key.equals(e.key)))//一直不断判断不重复才停止

  230. e = e.next;

  231.  
  232. V oldValue;

  233. if (e != null) { //这个key、hash已经存在,修改原来的

  234. oldValue = e.value;

  235. if (!onlyIfAbsent)

  236. e.value = value; //替换原来的旧值

  237. }

  238. else { //这个key、hash已经不存在,加入一个新的

  239. oldValue = null;

  240. ++modCount;

  241. tab[index] = new HashEntry<K,V>(key, hash, first, value);//加入一个新的元素

  242. count = c; // 个数变化

  243. }

  244. return oldValue;

  245. } finally {

  246. unlock();

  247. }

  248. }

  249.  
  250. //重新哈希

  251. void rehash() {

  252. HashEntry<K,V>[] oldTable = table;

  253. int oldCapacity = oldTable.length;//旧容量

  254. if (oldCapacity >= MAXIMUM_CAPACITY) //超过默认的最大容量时就退出了

  255. return;

  256.  
  257. HashEntry<K,V>[] newTable = HashEntry.newArray(oldCapacity<<1);//这里直接在原来的基础上扩大1倍

  258. threshold = (int)(newTable.length * loadFactor);//重新计算新的阈值

  259. int sizeMask = newTable.length - 1;

  260. for (int i = 0; i < oldCapacity ; i++) { //下面要做的就是将旧的table上的数据拷贝到新的table

  261. HashEntry<K,V> e = oldTable[i];

  262.  
  263. if (e != null) { //旧table上该处有数据

  264. HashEntry<K,V> next = e.next;

  265. int idx = e.hash & sizeMask;

  266.  
  267. // 单个节点key-value

  268. if (next == null)

  269. newTable[idx] = e;

  270.  
  271. else { //链表节点key-value

  272. HashEntry<K,V> lastRun = e;

  273. int lastIdx = idx;

  274. for (HashEntry<K,V> last = next;

  275. last != null;

  276. last = last.next) { //这里重新计算了链表上最后一个节点的位置

  277. int k = last.hash & sizeMask;

  278. if (k != lastIdx) {

  279. lastIdx = k;

  280. lastRun = last;

  281. }

  282. }

  283. newTable[lastIdx] = lastRun;//将原table上对应的链表上的最后一个元素放在新table对应链表的首位置

  284.  
  285. for (HashEntry<K,V> p = e; p != lastRun; p = p.next) { //for循环依次拷贝链表上的数据,注意最后整个链表相对原来会倒序排列

  286. int k = p.hash & sizeMask;

  287. HashEntry<K,V> n = newTable[k];

  288. newTable[k] = new HashEntry<K,V>(p.key, p.hash,

  289. n, p.value);//新table数据赋值

  290. }

  291. }

  292. }

  293. }

  294. table = newTable;

  295. }

  296.  
  297. //删除一个元素

  298. V remove(Object key, int hash, Object value) {

  299. lock(); //删除要加锁

  300. try {

  301. int c = count - 1;

  302. HashEntry<K,V>[] tab = table;

  303. int index = hash & (tab.length - 1);

  304. HashEntry<K,V> first = tab[index];

  305. HashEntry<K,V> e = first;

  306. while (e != null && (e.hash != hash || !key.equals(e.key)))

  307. e = e.next;

  308.  
  309. V oldValue = null;

  310. if (e != null) { ///找到元素

  311. V v = e.value;

  312. if (value == null || value.equals(v)) { //为null或者value相等时才删除

  313. oldValue = v;

  314. ++modCount;

  315. HashEntry<K,V> newFirst = e.next;

  316. for (HashEntry<K,V> p = first; p != e; p = p.next)

  317. newFirst = new HashEntry<K,V>(p.key, p.hash,

  318. newFirst, p.value);//注意它这里会倒换原来链表的位置

  319. tab[index] = newFirst;

  320. count = c; //记录数减去1

  321. }

  322. }

  323. return oldValue;

  324. } finally {

  325. unlock();

  326. }

  327. }

  328. //清空整个map

  329. void clear() {

  330. if (count != 0) {

  331. lock();

  332. try {

  333. HashEntry<K,V>[] tab = table;

  334. for (int i = 0; i < tab.length ; i++)

  335. tab[i] = null;//直接赋值为null

  336. ++modCount;

  337. count = 0; // write-volatile

  338. } finally {

  339. unlock();

  340. }

  341. }

  342. }

  343. }

  344.  
  345.  
  346.  
  347. //构造函数

  348. public ConcurrentHashMap(int initialCapacity,

  349. float loadFactor, int concurrencyLevel) {

  350. if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0) //loadFactor和initialCapacity都得大于0

  351. throw new IllegalArgumentException();

  352.  
  353. if (concurrencyLevel > MAX_SEGMENTS)

  354. concurrencyLevel = MAX_SEGMENTS;

  355.  
  356. // Find power-of-two sizes best matching arguments

  357. int sshift = 0;

  358. int ssize = 1;

  359. while (ssize < concurrencyLevel) {

  360. ++sshift;

  361. ssize <<= 1;

  362. }

  363. segmentShift = 32 - sshift;

  364. segmentMask = ssize - 1;

  365. this.segments = Segment.newArray(ssize);

  366.  
  367. if (initialCapacity > MAXIMUM_CAPACITY)

  368. initialCapacity = MAXIMUM_CAPACITY;

  369. int c = initialCapacity / ssize;

  370. if (c * ssize < initialCapacity)

  371. ++c;

  372. int cap = 1;

  373. while (cap < c)

  374. cap <<= 1;

  375.  
  376. for (int i = 0; i < this.segments.length; ++i)

  377. this.segments[i] = new Segment<K,V>(cap, loadFactor);//为每个segments初始化其里面的数组

  378. }

  379.  
  380. //构造函数

  381. public ConcurrentHashMap(int initialCapacity, float loadFactor) {

  382. this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);

  383. }

  384.  
  385.  
  386. //构造函数

  387. public ConcurrentHashMap(int initialCapacity) {

  388. this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);

  389. }

  390.  
  391.  
  392. //默认构造函数

  393. public ConcurrentHashMap() {

  394. this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);

  395. }

  396.  
  397. //构造函数

  398. public ConcurrentHashMap(Map<? extends K, ? extends V> m) {

  399. this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,

  400. DEFAULT_INITIAL_CAPACITY),

  401. DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);

  402. putAll(m);

  403. }

  404.  
  405. //判断 是否为空

  406. public boolean isEmpty() {

  407. final Segment<K,V>[] segments = this.segments;//取得整个Segment数组

  408.  
  409. int[] mc = new int[segments.length];

  410. int mcsum = 0;

  411. for (int i = 0; i < segments.length; ++i) {

  412. if (segments[i].count != 0) //有一个segments数组元素个数不为0,那么整个map肯定不为空

  413. return false;

  414. else

  415. mcsum += mc[i] = segments[i].modCount;//累加总的修改次数

  416. }

  417.  
  418. if (mcsum != 0) {

  419. for (int i = 0; i < segments.length; ++i) {

  420. if (segments[i].count != 0 ||

  421. mc[i] != segments[i].modCount)//这里又做了一次mc[i] != segments[i].modCount判断,因为segments[i].count = 0时才会跳到这里,不相等那么肯定是又有元素加入

  422. return false;

  423. }

  424. }

  425. return true;

  426. }

  427.  
  428. //整个mapr的大小,这里的大小指的是存放元素的个数

  429. public int size() {

  430. final Segment<K,V>[] segments = this.segments;

  431. long sum = 0;

  432. long check = 0;

  433. int[] mc = new int[segments.length];

  434.  
  435. //这是里的for循环是尝试在不加锁的情况下来获取整个map的元素个数

  436. for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) { //这里RETRIES_BEFORE_LOCK=2,最大会做两次的循环

  437. check = 0;

  438. sum = 0;

  439. int mcsum = 0;

  440. for (int i = 0; i < segments.length; ++i) {

  441. sum += segments[i].count;//累加每一个segments上的count

  442. mcsum += mc[i] = segments[i].modCount;//累加每一个segments上的modCount

  443. }

  444. if (mcsum != 0) { //修改次数不为0,要再做一次判断前后两次的modCount,count的累加

  445. for (int i = 0; i < segments.length; ++i) {

  446. check += segments[i].count;

  447. if (mc[i] != segments[i].modCount) { //前后两次数据发生了变化

  448. check = -1; // 前后两次取的个数不一到,注意sum还是之前的

  449. break;

  450. }

  451. }

  452. }

  453. if (check == sum) //前后两次取的元素个数一样,直接跳出循环

  454. break;

  455. }

  456.  
  457. //这里会尝试在加锁的情况下来获取整个map的元素个数

  458. if (check != sum) { // 这里一般check会等于-1才发生

  459. sum = 0;//重新置0

  460. for (int i = 0; i < segments.length; ++i)

  461. segments[i].lock();//每一个segments上锁

  462. for (int i = 0; i < segments.length; ++i)

  463. sum += segments[i].count;//重新累加

  464. for (int i = 0; i < segments.length; ++i)

  465. segments[i].unlock();//依次释放锁

  466. }

  467. if (sum > Integer.MAX_VALUE)

  468. return Integer.MAX_VALUE;//如果大于最大值,返回最大值

  469. else

  470. return (int)sum;

  471. }

  472.  
  473. //取得一个元素,先是不加锁情况下去读

  474. public V get(Object key) {

  475. int hash = hash(key.hashCode());

  476. return segmentFor(hash).get(key, hash);//具体看上面的代码注释

  477. }

  478.  
  479. //是否包含一个元素,根据key来获取

  480. public boolean containsKey(Object key) {

  481. int hash = hash(key.hashCode());

  482. return segmentFor(hash).containsKey(key, hash);

  483. }

  484.  
  485. //是否包含一个元素,根据value来获取

  486. public boolean containsValue(Object value) {

  487. if (value == null)

  488. throw new NullPointerException();

  489. //取得整个Segment的内容

  490. final Segment<K,V>[] segments = this.segments;

  491. int[] mc = new int[segments.length];

  492.  
  493. // 尝试在不加锁的情况下做判断

  494. for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) { //RETRIES_BEFORE_LOCK这里=2

  495. int sum = 0;

  496. int mcsum = 0;

  497. for (int i = 0; i < segments.length; ++i) {

  498. int c = segments[i].count;//累加个数

  499. mcsum += mc[i] = segments[i].modCount;//累加修改次数

  500. if (segments[i].containsValue(value)) //判断是否包含

  501. return true;

  502. }

  503. boolean cleanSweep = true;

  504. if (mcsum != 0) { //成立说明发生了改变

  505. for (int i = 0; i < segments.length; ++i) { //再循环一次取得segments

  506. int c = segments[i].count;//累加第二次循环得到的count

  507. if (mc[i] != segments[i].modCount) { //如果有一个segments前后两次不一样,那么它的元素肯定发生了变化

  508. cleanSweep = false;//

  509. break;//跳出

  510. }

  511. }

  512. }

  513. if (cleanSweep) //为ture表示经过上面的两次判断还是无法找到

  514. return false;

  515. }

  516.  
  517. // cleanSweepo为false时,进行下面。注意,这里是在加锁情况下

  518. for (int i = 0; i < segments.length; ++i)

  519. segments[i].lock();//取得每一个segments的锁

  520. boolean found = false;

  521. try {

  522. for (int i = 0; i < segments.length; ++i) { //每个segments取出来做判断

  523. if (segments[i].containsValue(value)) {

  524. found = true;

  525. break;

  526. }

  527. }

  528. } finally {

  529. for (int i = 0; i < segments.length; ++i) //依次释放segments的锁

  530. segments[i].unlock();

  531. }

  532. return found;

  533. }

  534.  
  535. //是否包含

  536. public boolean contains(Object value) {

  537. return containsValue(value);

  538. }

  539.  
  540. //放入一个元素

  541. public V put(K key, V value) {

  542. if (value == null)

  543. throw new NullPointerException();

  544. int hash = hash(key.hashCode());

  545. return segmentFor(hash).put(key, hash, value, false);//放入时先根据key的hash值找到存放 的segments,再调用其put方法

  546. }

  547.  
  548. //放入一个元素,如果key或value为null,那么为招出一个异常

  549. public V putIfAbsent(K key, V value) {

  550. if (value == null)

  551. throw new NullPointerException();

  552. int hash = hash(key.hashCode());

  553. return segmentFor(hash).put(key, hash, value, true);

  554. }

  555.  
  556. //放入一个map

  557. public void putAll(Map<? extends K, ? extends V> m) {

  558. for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) //遍历entrySet取出再放入

  559. put(e.getKey(), e.getValue());

  560. }

  561.  
  562. //删除一个元素,根据key

  563. public V remove(Object key) {

  564. int hash = hash(key.hashCode());

  565. return segmentFor(hash).remove(key, hash, null);//根据key的hash值找到存放的segments,再调用其remove方法

  566. }

  567.  
  568. //删除一个元素,根据key-value

  569. public boolean remove(Object key, Object value) {

  570. int hash = hash(key.hashCode());

  571. if (value == null)

  572. return false;

  573. return segmentFor(hash).remove(key, hash, value) != null;//根据key的hash值找到存放的segments,再调用其remove方法

  574. }

  575.  
  576. //替换元素

  577. public boolean replace(K key, V oldValue, V newValue) {

  578. if (oldValue == null || newValue == null)

  579. throw new NullPointerException();

  580. int hash = hash(key.hashCode());

  581. return segmentFor(hash).replace(key, hash, oldValue, newValue);//根据key的hash值找到存放的segments,再调用其replace方法

  582. }

  583.  
  584. //替换元素

  585. public V replace(K key, V value) {

  586. if (value == null)

  587. throw new NullPointerException();

  588. int hash = hash(key.hashCode());

  589. return segmentFor(hash).replace(key, hash, value);

  590. }

  591.  
  592. //清空

  593. public void clear() {

  594. for (int i = 0; i < segments.length; ++i)

  595. segments[i].clear();

  596. }

  597.  
  598.  
  599. //序列化方法

  600. private void writeObject(java.io.ObjectOutputStream s) throws IOException {

  601. s.defaultWriteObject();

  602.  
  603. for (int k = 0; k < segments.length; ++k) {

  604. Segment<K,V> seg = segments[k];

  605. seg.lock();//注意加锁了

  606. try {

  607. HashEntry<K,V>[] tab = seg.table;

  608. for (int i = 0; i < tab.length; ++i) {

  609. for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) {

  610. s.writeObject(e.key);

  611. s.writeObject(e.value);

  612. }

  613. }

  614. } finally {

  615. seg.unlock();

  616. }

  617. }

  618. s.writeObject(null);

  619. s.writeObject(null);

  620. }

  621.  
  622. //反序列化方法

  623. private void readObject(java.io.ObjectInputStream s)

  624. throws IOException, ClassNotFoundException {

  625. s.defaultReadObject();

  626.  
  627. for (int i = 0; i < segments.length; ++i) {

  628. segments[i].setTable(new HashEntry[1]);

  629. }

  630.  
  631. for (;;) {

  632. K key = (K) s.readObject();

  633. V value = (V) s.readObject();

  634. if (key == null)

  635. break;

  636. put(key, value);

  637. }

  638. }

  639. }

 

 

版权声明:本文为博主林炳文Evankaka原创文章,转载请注明出处http://blog.****.net/evankaka https://blog.****.net/Evankaka/article/details/51735036