HashSet

image.png
从类图中,可以看到, HashSet 继承了 AbstractSet 抽象类, 而 AbstractSet 又继承了 AbstractCollection 抽象类,此外,HashSet 还实现了 Set 接口等。
AbstractSet 抽象类主要实现了两个方法 equals 和 hashcode 方法,因为 HashSet 中没有重复元素,就是根据这两个方法来进行判断的:

  1. public boolean equals(Object o) {
  2. if (o == this)
  3. return true;
  4. if (!(o instanceof Set))
  5. return false;
  6. Collection<?> c = (Collection<?>) o;
  7. if (c.size() != size())
  8. return false;
  9. try {
  10. return containsAll(c);
  11. } catch (ClassCastException unused) {
  12. return false;
  13. } catch (NullPointerException unused) {
  14. return false;
  15. }
  16. }
  17. public int hashCode() {
  18. int h = 0;
  19. Iterator<E> i = iterator();
  20. while (i.hasNext()) {
  21. E obj = i.next();
  22. if (obj != null)
  23. h += obj.hashCode();
  24. }
  25. return h;
  26. }

Set 接口,它是一个顶层接口,主要定义了一些公共的方法,如 add, isEmpty, size, remove, contains 等一些方法;HashSet, SortedSet,TreeSet 都实现了该接口。

  1. public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable,
  2. java.io.Serializable
  3. {
  4. // 用来存放元素的 HashMap
  5. private transient HashMap<E,Object> map;
  6. // 因为 HashMap 是存放键值对的,而 HashSet 只会存放其中的key,即当做 HashMap 的key,
  7. // 而value 就是这个 Object 对象了,HashMap 中所有元素的 value 都是它
  8. private static final Object PRESENT = new Object();
  9. // 无参构造,创建 HashMap 对象,初始大小为 16
  10. public HashSet() {
  11. map = new HashMap<>();
  12. }
  13. public HashSet(Collection<? extends E> c) {
  14. map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
  15. addAll(c);
  16. }
  17. // 根据初始大小和加载因子创建 HashSet
  18. public HashSet(int initialCapacity, float loadFactor) {
  19. map = new HashMap<>(initialCapacity, loadFactor);
  20. }
  21. // 根据初始大小创建 HashSet
  22. public HashSet(int initialCapacity) {
  23. map = new HashMap<>(initialCapacity);
  24. }
  25. // 迭代器
  26. public Iterator<E> iterator() {
  27. return map.keySet().iterator();
  28. }
  29. .......
  30. }

从上面声明可看到,HashSet 底层是使用 HashMap 来存放元素的,且 HashMap 中所有元素的 value 都是同一个 Object 对象,且它被 final 修饰。

  1. // 返回集合中元素的个数
  2. public int size() {
  3. return map.size();
  4. }
  5. // 判断集合是否为空
  6. public boolean isEmpty() {
  7. return map.isEmpty();
  8. }
  9. // 集合中是否包含某个值,即判断 HashMap 中是否包含该key
  10. public boolean contains(Object o) {
  11. return map.containsKey(o);
  12. }
  13. // 添加元素,在这里可以看到,添加元素的时候,会向 HashMap 中添加,
  14. //且 HashMap中的value都是同一个 Object对象
  15. public boolean add(E e) {
  16. return map.put(e, PRESENT)==null;
  17. }
  18. // 删除元素
  19. public boolean remove(Object o) {
  20. return map.remove(o)==PRESENT;
  21. }
  22. // 清除集合
  23. public void clear() {
  24. map.clear();
  25. }
  1. HashSet 底层是使用 HashMap 来保存元素的
  2. 它不保证集合中存放元素的顺序,即是无序的,且这种顺序可能会随着时间的推移还会改变
  3. 允许 null 值,且只有一个
  4. HashSet底层的 HashMap 不是线程安全的,HashSet 自然也不是,可以使用 Collections.synchronizedSet(new HashSet())来创建线程安全的 HashSet
  5. 集合中的元素不会重复

    LinkedHashSet

    HashSet是无序的,LinkedHashSet是有序的。
    image.png
    底层实现是linkedhashmap,通过双向链表实现遍历顺序就是添加顺序。

    TreeSet, SortedSet

    111111.png
  1. package java.util;
  2. // TreeSet实现了NavigableSet接口,所以它是有序的
  3. public class TreeSet<E> extends AbstractSet<E>
  4. implements NavigableSet<E>, Cloneable, java.io.Serializable
  5. {
  6. // 元素存储在NavigableMap中
  7. // 注意它不一定就是TreeMap
  8. private transient NavigableMap<E,Object> m;
  9. // 虚拟元素, 用来作为value存储在map中
  10. private static final Object PRESENT = new Object();
  11. // 直接使用传进来的NavigableMap存储元素
  12. // 这里不是深拷贝,如果外面的map有增删元素也会反映到这里
  13. // 而且, 这个方法不是public的, 说明只能给同包使用
  14. TreeSet(NavigableMap<E,Object> m) {
  15. this.m = m;
  16. }
  17. // 使用TreeMap初始化
  18. public TreeSet() {
  19. this(new TreeMap<E,Object>());
  20. }
  21. // 使用带comparator的TreeMap初始化
  22. public TreeSet(Comparator<? super E> comparator) {
  23. this(new TreeMap<>(comparator));
  24. }
  25. // 将集合c中的所有元素添加的TreeSet中
  26. public TreeSet(Collection<? extends E> c) {
  27. this();
  28. addAll(c);
  29. }
  30. // 将SortedSet中的所有元素添加到TreeSet中
  31. public TreeSet(SortedSet<E> s) {
  32. this(s.comparator());
  33. addAll(s);
  34. }
  35. // 迭代器
  36. public Iterator<E> iterator() {
  37. return m.navigableKeySet().iterator();
  38. }
  39. // 逆序迭代器
  40. public Iterator<E> descendingIterator() {
  41. return m.descendingKeySet().iterator();
  42. }
  43. // 以逆序返回一个新的TreeSet
  44. public NavigableSet<E> descendingSet() {
  45. return new TreeSet<>(m.descendingMap());
  46. }
  47. // 元素个数
  48. public int size() {
  49. return m.size();
  50. }
  51. // 判断是否为空
  52. public boolean isEmpty() {
  53. return m.isEmpty();
  54. }
  55. // 判断是否包含某元素
  56. public boolean contains(Object o) {
  57. return m.containsKey(o);
  58. }
  59. // 添加元素, 调用map的put()方法, value为PRESENT
  60. public boolean add(E e) {
  61. return m.put(e, PRESENT)==null;
  62. }
  63. // 删除元素
  64. public boolean remove(Object o) {
  65. return m.remove(o)==PRESENT;
  66. }
  67. // 清空所有元素
  68. public void clear() {
  69. m.clear();
  70. }
  71. // 添加集合c中的所有元素
  72. public boolean addAll(Collection<? extends E> c) {
  73. // 满足一定条件时直接调用TreeMap的addAllForTreeSet()方法添加元素
  74. if (m.size()==0 && c.size() > 0 &&
  75. c instanceof SortedSet &&
  76. m instanceof TreeMap) {
  77. SortedSet<? extends E> set = (SortedSet<? extends E>) c;
  78. TreeMap<E,Object> map = (TreeMap<E, Object>) m;
  79. Comparator<?> cc = set.comparator();
  80. Comparator<? super E> mc = map.comparator();
  81. if (cc==mc || (cc != null && cc.equals(mc))) {
  82. map.addAllForTreeSet(set, PRESENT);
  83. return true;
  84. }
  85. }
  86. // 不满足上述条件, 调用父类的addAll()通过遍历的方式一个一个地添加元素
  87. return super.addAll(c);
  88. }
  89. // 子set(NavigableSet中的方法)
  90. public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
  91. E toElement, boolean toInclusive) {
  92. return new TreeSet<>(m.subMap(fromElement, fromInclusive,
  93. toElement, toInclusive));
  94. }
  95. // 头set(NavigableSet中的方法)
  96. public NavigableSet<E> headSet(E toElement, boolean inclusive) {
  97. return new TreeSet<>(m.headMap(toElement, inclusive));
  98. }
  99. // 尾set(NavigableSet中的方法)
  100. public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
  101. return new TreeSet<>(m.tailMap(fromElement, inclusive));
  102. }
  103. // 子set(SortedSet接口中的方法)
  104. public SortedSet<E> subSet(E fromElement, E toElement) {
  105. return subSet(fromElement, true, toElement, false);
  106. }
  107. // 头set(SortedSet接口中的方法)
  108. public SortedSet<E> headSet(E toElement) {
  109. return headSet(toElement, false);
  110. }
  111. // 尾set(SortedSet接口中的方法)
  112. public SortedSet<E> tailSet(E fromElement) {
  113. return tailSet(fromElement, true);
  114. }
  115. // 比较器
  116. public Comparator<? super E> comparator() {
  117. return m.comparator();
  118. }
  119. // 返回最小的元素
  120. public E first() {
  121. return m.firstKey();
  122. }
  123. // 返回最大的元素
  124. public E last() {
  125. return m.lastKey();
  126. }
  127. // 返回小于e的最大的元素
  128. public E lower(E e) {
  129. return m.lowerKey(e);
  130. }
  131. // 返回小于等于e的最大的元素
  132. public E floor(E e) {
  133. return m.floorKey(e);
  134. }
  135. // 返回大于等于e的最小的元素
  136. public E ceiling(E e) {
  137. return m.ceilingKey(e);
  138. }
  139. // 返回大于e的最小的元素
  140. public E higher(E e) {
  141. return m.higherKey(e);
  142. }
  143. // 弹出最小的元素
  144. public E pollFirst() {
  145. Map.Entry<E,?> e = m.pollFirstEntry();
  146. return (e == null) ? null : e.getKey();
  147. }
  148. public E pollLast() {
  149. Map.Entry<E,?> e = m.pollLastEntry();
  150. return (e == null) ? null : e.getKey();
  151. }
  152. // 克隆方法
  153. @SuppressWarnings("unchecked")
  154. public Object clone() {
  155. TreeSet<E> clone;
  156. try {
  157. clone = (TreeSet<E>) super.clone();
  158. } catch (CloneNotSupportedException e) {
  159. throw new InternalError(e);
  160. }
  161. clone.m = new TreeMap<>(m);
  162. return clone;
  163. }
  164. // 序列化写出方法
  165. private void writeObject(java.io.ObjectOutputStream s)
  166. throws java.io.IOException {
  167. // Write out any hidden stuff
  168. s.defaultWriteObject();
  169. // Write out Comparator
  170. s.writeObject(m.comparator());
  171. // Write out size
  172. s.writeInt(m.size());
  173. // Write out all elements in the proper order.
  174. for (E e : m.keySet())
  175. s.writeObject(e);
  176. }
  177. // 序列化写入方法
  178. private void readObject(java.io.ObjectInputStream s)
  179. throws java.io.IOException, ClassNotFoundException {
  180. // Read in any hidden stuff
  181. s.defaultReadObject();
  182. // Read in Comparator
  183. @SuppressWarnings("unchecked")
  184. Comparator<? super E> c = (Comparator<? super E>) s.readObject();
  185. // Create backing TreeMap
  186. TreeMap<E,Object> tm = new TreeMap<>(c);
  187. m = tm;
  188. // Read in size
  189. int size = s.readInt();
  190. tm.readTreeSet(size, s, PRESENT);
  191. }
  192. // 可分割的迭代器
  193. public Spliterator<E> spliterator() {
  194. return TreeMap.keySpliteratorFor(m);
  195. }
  196. // 序列化id
  197. private static final long serialVersionUID = -2479143000061671589L;
  198. }
  1. TreeSet底层使用NavigableMap存储元素;
  2. TreeSet是有序的;
  3. TreeSet是非线程安全的;
  4. TreeSet实现了NavigableSet接口,而NavigableSet继承自SortedSet接口;

LinkedHashSet并没有实现SortedSet接口,它的有序性主要依赖于LinkedHashMap的有序性,所以它的有序性是指按照插入顺序保证的有序性;
而TreeSet实现了SortedSet接口,它的有序性主要依赖于NavigableMap的有序性,而NavigableMap又继承自SortedMap,这个接口的有序性是指按照key的自然排序保证的有序性,而key的自然排序又有两种实现方式,一种是key实现Comparable接口,一种是构造方法传入Comparator比较器。

CopyOnWriteArraySet

CopyOnWriteArraySet底层是使用CopyOnWriteArrayList存储元素的,所以它并不是使用Map来存储元素的。
但是,我们知道CopyOnWriteArrayList底层其实是一个数组,它是允许元素重复的,那么用它来实现CopyOnWriteArraySet怎么保证元素不重复呢?

  1. public class CopyOnWriteArraySet<E> extends AbstractSet<E>
  2. implements java.io.Serializable {
  3. private static final long serialVersionUID = 5457747651344034263L;
  4. // 内部使用CopyOnWriteArrayList存储元素
  5. private final CopyOnWriteArrayList<E> al;
  6. // 构造方法
  7. public CopyOnWriteArraySet() {
  8. al = new CopyOnWriteArrayList<E>();
  9. }
  10. // 将集合c中的元素初始化到CopyOnWriteArraySet中
  11. public CopyOnWriteArraySet(Collection<? extends E> c) {
  12. if (c.getClass() == CopyOnWriteArraySet.class) {
  13. // 如果c是CopyOnWriteArraySet类型,说明没有重复元素,
  14. // 直接调用CopyOnWriteArrayList的构造方法初始化
  15. @SuppressWarnings("unchecked") CopyOnWriteArraySet<E> cc =
  16. (CopyOnWriteArraySet<E>)c;
  17. al = new CopyOnWriteArrayList<E>(cc.al);
  18. }
  19. else {
  20. // 如果c不是CopyOnWriteArraySet类型,说明有重复元素
  21. // 调用CopyOnWriteArrayList的addAllAbsent()方法初始化
  22. // 它会把重复元素排除掉
  23. al = new CopyOnWriteArrayList<E>();
  24. al.addAllAbsent(c);
  25. }
  26. }
  27. // 获取元素个数
  28. public int size() {
  29. return al.size();
  30. }
  31. // 检查集合是否为空
  32. public boolean isEmpty() {
  33. return al.isEmpty();
  34. }
  35. // 检查是否包含某个元素
  36. public boolean contains(Object o) {
  37. return al.contains(o);
  38. }
  39. // 集合转数组
  40. public Object[] toArray() {
  41. return al.toArray();
  42. }
  43. // 集合转数组
  44. public <T> T[] toArray(T[] a) {
  45. return al.toArray(a);
  46. }
  47. // 清空所有元素
  48. public void clear() {
  49. al.clear();
  50. }
  51. // 删除元素
  52. public boolean remove(Object o) {
  53. return al.remove(o);
  54. }
  55. // 添加元素
  56. // 这里是调用CopyOnWriteArrayList的addIfAbsent()方法
  57. // 它会检测元素不存在的时候才添加
  58. public boolean add(E e) {
  59. return al.addIfAbsent(e);
  60. }
  61. // 是否包含c中的所有元素
  62. public boolean containsAll(Collection<?> c) {
  63. return al.containsAll(c);
  64. }
  65. // 并集
  66. public boolean addAll(Collection<? extends E> c) {
  67. return al.addAllAbsent(c) > 0;
  68. }
  69. // 单方向差集
  70. public boolean removeAll(Collection<?> c) {
  71. return al.removeAll(c);
  72. }
  73. // 交集
  74. public boolean retainAll(Collection<?> c) {
  75. return al.retainAll(c);
  76. }
  77. // 迭代器
  78. public Iterator<E> iterator() {
  79. return al.iterator();
  80. }
  81. // equals()方法
  82. public boolean equals(Object o) {
  83. // 如果两者是同一个对象,返回true
  84. if (o == this)
  85. return true;
  86. // 如果o不是Set对象,返回false
  87. if (!(o instanceof Set))
  88. return false;
  89. Set<?> set = (Set<?>)(o);
  90. Iterator<?> it = set.iterator();
  91. // 集合元素数组的快照
  92. Object[] elements = al.getArray();
  93. int len = elements.length;
  94. boolean[] matched = new boolean[len];
  95. int k = 0;
  96. // 从o这个集合开始遍历
  97. outer: while (it.hasNext()) {
  98. // 如果k>len了,说明o中元素多了
  99. if (++k > len)
  100. return false;
  101. // 取值
  102. Object x = it.next();
  103. // 遍历检查是否在当前集合中
  104. for (int i = 0; i < len; ++i) {
  105. if (!matched[i] && eq(x, elements[i])) {
  106. matched[i] = true;
  107. continue outer;
  108. }
  109. }
  110. // 如果不在当前集合中,返回false
  111. return false;
  112. }
  113. return k == len;
  114. }
  115. // 移除满足过滤条件的元素
  116. public boolean removeIf(Predicate<? super E> filter) {
  117. return al.removeIf(filter);
  118. }
  119. // 遍历元素
  120. public void forEach(Consumer<? super E> action) {
  121. al.forEach(action);
  122. }
  123. // 分割的迭代器
  124. public Spliterator<E> spliterator() {
  125. return Spliterators.spliterator
  126. (al.getArray(), Spliterator.IMMUTABLE | Spliterator.DISTINCT);
  127. }
  128. // 比较两个元素是否相等
  129. private static boolean eq(Object o1, Object o2) {
  130. return (o1 == null) ? o2 == null : o1.equals(o2);
  131. }
  132. }

(1)CopyOnWriteArraySet是用CopyOnWriteArrayList实现的;
(2)CopyOnWriteArraySet是有序的,因为底层其实是数组;
(3)CopyOnWriteArraySet是并发安全的,而且实现了读写分离;
(4)CopyOnWriteArraySet通过调用CopyOnWriteArrayList的addIfAbsent()方法来保证元素不重复;

ConcurrentSkipListSet

把前面偷工减料的skiplist补了一遍。
ConcurrentSkipListSet是一个有序的线程安全的集合,基本上都是使用ConcurrentSkipListMap实现的。

ConcurrentSkipListMap

内部节点Node
  1. static final class Node<K, V>{
  2. final K key; // key 是 final 的, 说明节点一旦定下来, 除了删除, 不然不会改动 key 了
  3. volatile Object value; // 对应的 value
  4. volatile Node<K, V> next; // 下一个节点
  5. // 构造函数
  6. public Node(K key, Object value, Node<K, V> next) {
  7. this.key = key;
  8. this.value = value;
  9. this.next = next;
  10. }
  11. /**
  12. * 创建一个标记节点(通过 this.value = this 来标记)
  13. * 这个标记节点非常重要: 有了它, 就能对链表中间节点进行同时删除和插入
  14. * ps: ConcurrentLinkedQueue 只能在头上, 尾端进行插入, 中间进行删除
  15. */
  16. public Node(Node<K, V> next) {
  17. this.key = null;
  18. this.value = this;
  19. this.next = next;
  20. }
  21. /**
  22. * CAS 操作设置 Value
  23. */
  24. boolean casValue(Object cmp, Object val){
  25. return unsafe.compareAndSwapObject(this, valueOffset, cmp, val);
  26. }
  27. /**
  28. * CAS 操作设置 next
  29. */
  30. boolean casNext(Node<K, V> cmp, Node<K, V> val){
  31. return unsafe.compareAndSwapObject(this, nextOffset, cmp, val);
  32. }
  33. /**
  34. * 检测是否为标记节点
  35. */
  36. boolean isMarker(){
  37. return value == this;
  38. }
  39. /**
  40. * 检测是否为 链表最左下角的 BASE_HEADER 节点
  41. */
  42. boolean isBaseHeader(){
  43. return value == BASE_HEADER;
  44. }
  45. /**
  46. * 对节点追加一个标记节点, 为最终的删除做准备
  47. */
  48. boolean appendMarker(Node<K, V> f){
  49. return casNext(f, new Node<K, V>(f));
  50. }
  51. /**
  52. * Help out a deletion by appending marker or unlinking from
  53. * predecessor. This called during traversals when value
  54. * field seen to be null
  55. *
  56. * helpDelete 方法, 这个方法要么追加一个标记节点, 要么进行删除操作
  57. */
  58. void helpDelete(Node<K, V> b, Node<K, V> f){
  59. /**
  60. * Rechecking links and then doing only one of the
  61. * help-out stages per call tends to minimize CAS
  62. * interference among helping threads
  63. */
  64. if(f == next && this == b.next){
  65. if(f == null || f.value != f){ // 还没有对删除的节点进行节点 marker
  66. casNext(f, new Node<K, V>(f));
  67. }else{
  68. b.casNext(this, f.next); // 删除 节点 b 与 f.next 之间的节点
  69. }
  70. }
  71. }
  72. /**
  73. * 校验数据
  74. */
  75. V getValidValue(){
  76. Object v = value;
  77. if(v == this || v == BASE_HEADER){
  78. return null;
  79. }
  80. V vv = (V)v;
  81. return vv;
  82. }
  83. /**
  84. * Creates and returns a new SimpleImmutableEntry holding current
  85. * mapping if this node holds a valid value, else null.
  86. *
  87. * @return new entry or null
  88. */
  89. AbstractMap.SimpleImmutableEntry<K, V> createSnapshot(){
  90. Object v = value;
  91. if(v == null || v == this || v == BASE_HEADER){
  92. return null;
  93. }
  94. V vv = (V) v;
  95. return new AbstractMap.SimpleImmutableEntry<K, V>(key, vv);
  96. }
  97. // UNSAFE mechanics
  98. private static final Unsafe unsafe;
  99. private static final long valueOffset;
  100. private static final long nextOffset;
  101. static {
  102. try {
  103. unsafe = UnSafeClass.getInstance();
  104. Class<?> k = Node.class;
  105. valueOffset = unsafe.objectFieldOffset(k.getDeclaredField("value"));
  106. nextOffset = unsafe.objectFieldOffset(k.getDeclaredField("next"));
  107. }catch (Exception e){
  108. throw new Error(e);
  109. }
  110. }
  111. }

index
  1. static class Index<K, V>{
  2. final Node<K, V> node; // 索引指向的节点, 纵向上所有索引指向链表最下面的节点
  3. final Index<K, V> down; // 下边level层的 Index
  4. volatile Index<K, V> right; // 右边的 Index
  5. /**
  6. * Creates index node with given values
  7. * @param node
  8. * @param down
  9. * @param right
  10. */
  11. public Index(Node<K, V> node, Index<K, V> down, Index<K, V> right) {
  12. this.node = node;
  13. this.down = down;
  14. this.right = right;
  15. }
  16. /**
  17. * compareAndSet right field
  18. * @param cmp
  19. * @param val
  20. * @return
  21. */
  22. final boolean casRight(Index<K, V> cmp, Index<K, V> val){
  23. return unsafe.compareAndSwapObject(this, rightOffset, cmp, val);
  24. }
  25. /**
  26. * Returns true if the node this indexes has been deleted.
  27. * @return true if indexed node is known to be deleted
  28. */
  29. final boolean indexesDeletedNode(){
  30. return node.value == null;
  31. }
  32. /**
  33. * Tries to CAS newSucc as successor. To minimize races with
  34. * unlink that may lose this index node, if the node being
  35. * indexed is known to be deleted, it doesn't try to link in
  36. *
  37. * @param succ the expecteccurrent successor
  38. * @param newSucc the new successor
  39. * @return true if successful
  40. */
  41. /**
  42. * 在 index 本身 和 succ 之间插入一个新的节点 newSucc
  43. * @param succ
  44. * @param newSucc
  45. * @return
  46. */
  47. final boolean link(Index<K, V> succ, Index<K, V> newSucc){
  48. Node<K, V> n = node;
  49. newSucc.right = succ;
  50. return n.value != null && casRight(succ, newSucc);
  51. }
  52. /**
  53. * Tries to CAS field to skip over apparent successor
  54. * succ. Fails (forcing a retravesal by caller) if this node
  55. * is known to be deleted
  56. * @param succ the expected current successor
  57. * @return true if successful
  58. */
  59. /**
  60. * 将当前的节点 index 设置其的 right 为 succ.right 等于删除 succ 节点
  61. * @param succ
  62. * @return
  63. */
  64. final boolean unlink(Index<K, V> succ){
  65. return node.value != null && casRight(succ, succ.right);
  66. }
  67. // Unsafe mechanics
  68. private static final Unsafe unsafe;
  69. private static final long rightOffset;
  70. static {
  71. try{
  72. unsafe = UnSafeClass.getInstance();
  73. Class<?> k = Index.class;
  74. rightOffset = unsafe.objectFieldOffset(k.getDeclaredField("right"));
  75. }catch (Exception e){
  76. throw new Error(e);
  77. }

doPut()

1.初始状态:只存在 HeadIndex 和 Base_Header 节点
image.png
2.节点添加
image.png

  1. /**
  2. * Main insetion method. Adds element if not present, or
  3. * replaces value if present and onlyIfAbsent is false.
  4. *
  5. * @param key the key
  6. * @param value the values that must be associated with key
  7. * @param onlyIfAbstsent if should not insert if already present
  8. * @return the old value, or null if newly inserted
  9. */
  10. private V doPut(K key, V value, boolean onlyIfAbstsent){
  11. Node<K, V> z; // adde node
  12. if(key == null){
  13. throw new NullPointerException();
  14. }
  15. Comparator<? super K> cmp = comparator;
  16. outer:
  17. for(;;){
  18. // 0.
  19. for(Node<K, V> b = findPredecessor(key, cmp), n = b.next;;){ // 1. 将 key 对应的前继节点找到, b 为前继节点, n是前继节点的next, 若没发生 条件竞争, 最终 key在 b 与 n 之间 (找到的b在 base_level 上)
  20. if(n != null){ // 2. n = null时 b 是链表的最后一个节点, key 直接插到 b 之后 (调用 b.casNext(n, z))
  21. Object v; int c;
  22. Node<K, V> f = n.next; // 3 获取 n 的右节点
  23. if(n != b.next){ // 4. 条件竞争(另外一个线程在b之后插入节点, 或直接删除节点n), 则 break 到位置 0, 重新
  24. break ;
  25. }
  26. if((v = n.value) == null){ // 4. 若 节点n已经删除, 则 调用 helpDelete 进行帮助删除 (详情见 helpDelete), 则 break 到位置 0, 重新来
  27. n.helpDelete(b, f);
  28. break ;
  29. }
  30. if(b.value == null || v == n){ // 5. 节点b被删除中 ,则 break 到位置 0, 调用 findPredecessor 帮助删除 index 层的数据, 至于 node 层的数据 会通过 helpDelete 方法进行删除
  31. break ;
  32. }
  33. if((c = cpr(cmp, key, n.key)) > 0){ // 6. 若 key 真的 > n.key (在调用 findPredecessor 时是成立的), 则进行 向后走
  34. b = n;
  35. n = f;
  36. continue ;
  37. }
  38. if(c == 0){ // 7. 直接进行赋值
  39. if(onlyIfAbstsent || n.casValue(v, value)){
  40. V vv = (V) v;
  41. return vv;
  42. }
  43. break ; // 8. cas 竞争条件失败 重来
  44. }
  45. // else c < 0; fall through
  46. }
  47. // 9. 到这边时 n.key > key > b.key
  48. z = new Node<K, V> (key, value, n);
  49. if(!b.casNext(n, z)){
  50. break ; // 10. cas竞争条件失败 重来
  51. }
  52. break outer; // 11. 注意 这里 break outer 后, 上面的 for循环不会再执行, 而后执行下面的代码, 这里是break 不是 continue outer, 这两者的效果是不一样的
  53. }
  54. }
  55. int rnd = KThreadLocalRandom.nextSecondarySeed();
  56. if((rnd & 0x80000001) == 0){ // 12. 判断是否需要添加level
  57. int level = 1, max;
  58. while(((rnd >>>= 1) & 1) != 0){
  59. ++level;
  60. }
  61. // 13. 上面这段代码是获取 level 的, 我们这里只需要知道获取 level 就可以 (50%的几率返回0,25%的几率返回1,12.5%的几率返回2...最大返回31。)
  62. Index<K, V> idx = null;
  63. HeadIndex<K, V> h = head;
  64. if(level <= (max = h.level)){ // 14. 初始化 max 的值, 若 level 小于 max , 则进入这段代码 (level 是 1-31 之间的随机数)
  65. for(int i = 1; i <= level; ++i){
  66. idx = new Index<K, V>(z, idx, null); // 15 添加 z 对应的 index 数据, 并将它们组成一个上下的链表(index层是上下左右都是链表)
  67. }
  68. }
  69. else{ // 16. 若 level > max 则只增加一层 index 索引层
  70. level = max + 1; // 17. 跳表新的 level 产生
  71. Index<K, V>[] idxs = (Index<K, V>[])new Index<?, ?>[level + 1];
  72. for(int i = 1; i <= level; ++i){
  73. idxs[i] = idx = new Index<K, V>(z, idx, null);
  74. }
  75. for(;;){
  76. h = head;
  77. int oldLevel = h.level; // 18. 获取老的 level 层
  78. if(level <= oldLevel){ // 19. 另外的线程进行了index 层增加操作, 所以 不需要增加 HeadIndex 层数
  79. break;
  80. }
  81. HeadIndex<K, V> newh = h;
  82. Node<K, V> oldbase = h.node; // 20. 这里的 oldbase 就是BASE_HEADER
  83. for(int j = oldLevel+1; j <= level; ++j){ // 21. 这里其实就是增加一层的 HeadIndex (level = max + 1)
  84. newh = new HeadIndex<K, V>(oldbase, newh, idxs[j], j); // 22. idxs[j] 就是上面的 idxs中的最高层的索引
  85. }
  86. if(casHead(h, newh)){ // 23. 这只新的 headIndex
  87. h = newh; // 24. 这里的 h 变成了 new HeadIndex
  88. idx = idxs[level = oldLevel]; // 25. 这里的 idx 上从上往下第二层的 index 节点 level 也变成的 第二
  89. break;
  90. }
  91. }
  92. }
  93. // find insertion points and splice in
  94. splice:
  95. for(int insertionLevel = level;;){ // 26. 这时的 level 已经是 第二高的 level(若上面 步骤19 条件竞争失败, 则多出的 index 层其实是无用的, 因为 那是 调用 Index.right 是找不到它的)
  96. int j = h.level;
  97. for(Index<K, V> q = h, r = q.right, t = idx;;){ // 27. 初始化对应的数据
  98. if(q == null || t == null){ // 28. 节点都被删除 直接 break出去
  99. break splice;
  100. }
  101. if(r != null){
  102. Node<K, V> n = r.node;
  103. // compare before deletion check avoids needing recheck
  104. int c = cpr(cmp, key, n.key);
  105. if(n.value == null){ // 29. 老步骤, 帮助index 的删除
  106. if(!q.unlink(r)){
  107. break ;
  108. }
  109. r = q.right; // 30. 向右进行遍历
  110. continue ;
  111. }
  112. if(c > 0){ // 31. 向右进行遍历
  113. q = r;
  114. r = r.right;
  115. continue ;
  116. }
  117. }
  118. // 32.
  119. // 代码运行到这里, 说明 key < n.key
  120. // 第一次运行到这边时, j 是最新的 HeadIndex 的level j > insertionLevel 非常用可能, 而下面又有 --j, 所以终会到 j == insertionLevel
  121. if(j == insertionLevel){
  122. if(!q.link(r, t)){ // 33. 将 index t 加到 q 与 r 中间, 若条件竞争失败的话就重试
  123. break ; // restrt
  124. }
  125. if(t.node.value == null){ // 34. 若这时 node 被删除, 则开始通过 findPredecessor 清理 index 层, findNode 清理 node 层, 之后直接 break 出去, doPut调用结束
  126. findNode(key);
  127. break splice;
  128. }
  129. if(--insertionLevel == 0){ // 35. index 层添加OK, --1 为下层插入 index 做准备
  130. break splice;
  131. }
  132. }
  133. /**
  134. * 下面这行代码其实是最重要的, 理解这行代码, 那 doPut 就差不多了
  135. * 1). --j 要知道 j 是 newhead 的level, 一开始一定 > insertionLevel的, 通过 --1 来为下层操作做准备 (j 是 headIndex 的level)
  136. * 2). 通过 19. 21, 22 步骤, 个人认为 --j >= insertionLevel 是横成立, 而 --j 是必须要做的
  137. * 3) j 经过几次--1, 当出现 j < level 时说明 (j+1) 层的 index已经添加成功, 所以处理下层的 index
  138. */
  139. if(--j >= insertionLevel && j < level){
  140. t = t.down;
  141. }
  142. /** 到这里时, 其实有两种情况
  143. * 1) 还没有一次index 层的数据插入
  144. * 2) 已经进行 index 层的数据插入, 现在为下一层的插入做准备
  145. */
  146. q = q.down; // 从 index 层向下进行查找
  147. r = q.right;
  148. }
  149. }
  150. }
  151. return null;
  152. }

https://www.jianshu.com/p/edc2fd149255
未完待续…太难了。