HashMap
来源:互联网 发布:java api文档在哪里 编辑:程序博客网 时间:2024/06/18 13:50
1、HashMap简介
HashMap 的是一个散列表,它存储的内容是键值对(key-value)映射。
HashMap 继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。
HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。
1.2 构造函数
HashMap()构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。HashMap(int initialCapacity)构造一个空的 HashMap具有指定的初始容量和默认负载因子(0.75)。HashMap(int initialCapacity, float loadFactor)构造一个空的 HashMap具有指定的初始容量和负载因子。HashMap(Map<? extends K,? extends V> m)构造一个新的 HashMap与指定的相同的映射 Map 。
1.3 API
void clear()从这张地图中删除所有的映射。Object clone()返回此 HashMap实例的浅拷贝:键和值本身不被克隆。V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)尝试计算用于指定键和其当前映射的值的映射(或 null如果没有当前映射)。V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)如果指定的键尚未与值相关联(或映射到 null ),则尝试使用给定的映射函数计算其值,并将其输入到此映射中,除非 null 。V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)如果指定的密钥的值存在且非空,则尝试计算给定密钥及其当前映射值的新映射。boolean containsKey(Object key)如果此映射包含指定键的映射,则返回 true 。boolean containsValue(Object value)如果此地图将一个或多个键映射到指定值,则返回 true 。Set<Map.Entry<K,V>> entrySet()返回此地图中包含的映射的Set视图。void forEach(BiConsumer<? super K,? super V> action)对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。V get(Object key)返回到指定键所映射的值,或 null如果此映射包含该键的映射。V getOrDefault(Object key, V defaultValue)返回到指定键所映射的值,或 defaultValue如果此映射包含该键的映射。boolean isEmpty()如果此地图不包含键值映射,则返回 true 。Set<K> keySet()返回此地图中包含的键的Set视图。V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)如果指定的键尚未与值相关联或与null相关联,则将其与给定的非空值相关联。V put(K key, V value)将指定的值与此映射中的指定键相关联。void putAll(Map<? extends K,? extends V> m)将指定地图的所有映射复制到此地图。V putIfAbsent(K key, V value)如果指定的键尚未与某个值相关联(或映射到 null ),则将其与给定值相关联并返回 null ,否则返回当前值。V remove(Object key)从该地图中删除指定键的映射(如果存在)。boolean remove(Object key, Object value)仅当指定的密钥当前映射到指定的值时删除该条目。V replace(K key, V value)只有当目标映射到某个值时,才能替换指定键的条目。boolean replace(K key, V oldValue, V newValue)仅当当前映射到指定的值时,才能替换指定键的条目。void replaceAll(BiFunction<? super K,? super V,? extends V> function)将每个条目的值替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常。int size()返回此地图中键值映射的数量。Collection<V> values()返回此地图中包含的值的Collection视图。
1.4 继承关系
java.lang.Object ↳ java.util.AbstractMap<K, V> ↳ java.util.HashMap<K, V>public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { }
2、源代码
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { //初始化容量 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 //最大容量 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; final K key; V value; Node<K,V> next; Node(int hash, K key, V value, Node<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } public final K getKey() { return key; } public final V getValue() { return value; } public final String toString() { return key + "=" + value; } public final int hashCode() { return Objects.hashCode(key) ^ Objects.hashCode(value); } public final V setValue(V newValue) { V oldValue = value; value = newValue; return oldValue; } public final boolean equals(Object o) { if (o == this) return true; if (o instanceof Map.Entry) { Map.Entry<?,?> e = (Map.Entry<?,?>)o; if (Objects.equals(key, e.getKey()) && Objects.equals(value, e.getValue())) return true; } return false; } } //对key进行hash static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } //如果x继承Comparable且Comparable的泛型是x的类型 返回x的类型 static Class<?> comparableClassFor(Object x) { if (x instanceof Comparable) { Class<?> c; Type[] ts, as; Type t; ParameterizedType p; if ((c = x.getClass()) == String.class) // bypass checks return c; //获取x的接口(包括接口的泛型信息) if ((ts = c.getGenericInterfaces()) != null) { for (int i = 0; i < ts.length; ++i) { if (((t = ts[i]) instanceof ParameterizedType) && ((p = (ParameterizedType)t).getRawType() == Comparable.class) && //获取接口的泛型信息 (as = p.getActualTypeArguments()) != null && as.length == 1 && as[0] == c) // type arg is c return c; } } } return null; } //获取大于cap最小的二次幂数值 static final int tableSizeFor(int cap) { int n = cap - 1; n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16; return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; } //存储元素的数组,总是2的幂次倍数 transient Node<K,V>[] table; //存放元素的集 transient Set<Map.Entry<K,V>> entrySet; //元素的个数 transient int size; //fail-fast transient int modCount; // 临界值 超过临界值,会进行扩容 临界值=总容量*填充因子 int threshold; // 填充因子 final float loadFactor; //带初始容量和扩充因子的构造 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); } //带初始容量的构造 public HashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } //默认构造 public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted } //构造一个新的 HashMap与指定的相同的映射 Map 。 public HashMap(Map<? extends K, ? extends V> m) { this.loadFactor = DEFAULT_LOAD_FACTOR; putMapEntries(m, false); } //将m放入HashMap final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) { int s = m.size(); if (s > 0) { //如果table未初始化 if (table == null) { // pre-size //元素个数/填充因子=预计的容量 float ft = ((float)s / loadFactor) + 1.0F; int t = ((ft < (float)MAXIMUM_CAPACITY) ? (int)ft : MAXIMUM_CAPACITY); //如果大于临界值, if (t > threshold) //计算新的临界值 threshold = tableSizeFor(t); } else if (s > threshold) //扩容 resize(); for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) { K key = e.getKey(); V value = e.getValue(); //将m的数据放入hashmap putVal(hash(key), key, value, false, evict); } } } //根据键获取值 public V get(Object key) { Node<K,V> e; return (e = getNode(hash(key), key)) == null ? null : e.value; } //根据键获取值 final Node<K,V> getNode(int hash, Object key) { Node<K,V>[] tab; Node<K,V> first, e; int n; K k; //如果table有值,且key所在桶中有值 if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { //如果第一个就是要找的 直接返回 if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; //如果桶中的节点数大于1个 if ((e = first.next) != null) { //如果是红黑树 if (first instanceof TreeNode) //通过树查找 return ((TreeNode<K,V>)first).getTreeNode(hash, key); //单链表的遍历、查找 do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; } //存储键值对 public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } //放入键值对 //如果onlyIfAbsent=true 不能改变已存在的值 evict=false进入创建模式 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; //如果table未初始化,则使用resize初始化 if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; //如果key的位置没有值,直接创建链表节点 //n-1为数组长度 hash为key的hash值 if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); //如果hash碰撞 else { Node<K,V> e; K k; //如果key相同,将p赋给e if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; //如果是红黑树树 else if (p instanceof TreeNode) //调用TreeNode的putTreeVal e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); //链表结构 else { for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { //插入链表尾 p.next = newNode(hash, key, value, null); //如果此链表的元素大于TREEIFY_THRESHOLD 则将链表转为红黑树 if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } //如果在链表中找到key break;否则继续循环 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } //如果已经存在key if (e != null) { // existing mapping for key V oldValue = e.value; //如果允许更改值或值为null 直接覆盖value值 if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; //如果元素个数大于临界值,则扩展 if (++size > threshold) resize(); afterNodeInsertion(evict); return null; } //扩展容量 final Node<K,V>[] resize() { // 保存table对象 Node<K,V>[] oldTab = table; int oldCap = (oldTab == null) ? 0 : oldTab.length; //保存临界值 int oldThr = threshold; int newCap, newThr = 0; //如果之前HashMap容量大于0 if (oldCap > 0) { //如果之前HashMap容量大于最大容量 直接返回table if (oldCap >= MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return oldTab; } //将容量*2 如果在允许范围内允许范围内,临界值也*2 else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) newThr = oldThr << 1; // double threshold } //为临界值赋值 else if (oldThr > 0) // initial capacity was placed in threshold newCap = oldThr; //初始容量和临界值 else { // zero initial threshold signifies using defaults newCap = DEFAULT_INITIAL_CAPACITY; newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); } //threshold为Cap * loadFactor if (newThr == 0) { float ft = (float)newCap * loadFactor; newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? (int)ft : Integer.MAX_VALUE); } threshold = newThr; @SuppressWarnings({"rawtypes","unchecked"}) //根据新容量,创建新数组 Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; table = newTab; if (oldTab != null) { //for循环为新数组赋值 for (int j = 0; j < oldCap; ++j) { Node<K,V> e; //如果原数组j位置不为null,保存为临时变量e if ((e = oldTab[j]) != null) { //赋为null 进行释放 oldTab[j] = null; //如果j位置只有一个元素 直接根据新容量找到位置并赋值 if (e.next == null) newTab[e.hash & (newCap - 1)] = e; //如果是红黑树 else if (e instanceof TreeNode) ((TreeNode<K,V>)e).split(this, newTab, j, oldCap); //如果是链表 如果(e.hash & oldCap)==0 将元素放在原位置,否则偏移oldCap 不是很明白原因 else { // preserve order Node<K,V> loHead = null, loTail = null; Node<K,V> hiHead = null, hiTail = null; Node<K,V> next; do { next = e.next; if ((e.hash & oldCap) == 0) { if (loTail == null) loHead = e; else loTail.next = e; loTail = e; } else { if (hiTail == null) hiHead = e; else hiTail.next = e; hiTail = e; } } while ((e = next) != null); if (loTail != null) { loTail.next = null; newTab[j] = loHead; } if (hiTail != null) { hiTail.next = null; newTab[j + oldCap] = hiHead; } } } } } return newTab; } //链表转为树结构 final void treeifyBin(Node<K,V>[] tab, int hash) { int n, index; Node<K,V> e; //如果容量太小 直接扩展 if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) resize(); else if ((e = tab[index = (n - 1) & hash]) != null) { TreeNode<K,V> hd = null, tl = null; do { //将Node转换为TreeNode TreeNode<K,V> p = replacementTreeNode(e, null); if (tl == null) hd = p; else { p.prev = tl; tl.next = p; } tl = p; } while ((e = e.next) != null); if ((tab[index] = hd) != null) //转换为红黑树结构 hd.treeify(tab); } } //移除 public V remove(Object key) { Node<K,V> e; return (e = removeNode(hash(key), key, null, false, true)) == null ? null : e.value; } //移除节点的具体操作 final Node<K,V> removeNode(int hash, Object key, Object value, boolean matchValue, boolean movable) { Node<K,V>[] tab; Node<K,V> p; int n, index; //找到key对应的节点 if ((tab = table) != null && (n = tab.length) > 0 && (p = tab[index = (n - 1) & hash]) != null) { Node<K,V> node = null, e; K k; V v; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) node = p; else if ((e = p.next) != null) { if (p instanceof TreeNode) node = ((TreeNode<K,V>)p).getTreeNode(hash, key); else { do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { node = e; break; } p = e; } while ((e = e.next) != null); } } //移除 if (node != null && (!matchValue || (v = node.value) == value || (value != null && value.equals(v)))) { if (node instanceof TreeNode) ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable); else if (node == p) tab[index] = node.next; else p.next = node.next; ++modCount; --size; afterNodeRemoval(node); return node; } } return null; } //返回“key的集合”,实际上返回一个“KeySet对象” public Set<Map.Entry<K,V>> entrySet() { Set<Map.Entry<K,V>> es; return (es = entrySet) == null ? (entrySet = new EntrySet()) : es; } //返回“key的集合”,实际上返回一个“KeySet对象” final class EntrySet extends AbstractSet<Map.Entry<K,V>> { public final int size() { return size; } public final void clear() { HashMap.this.clear(); } public final Iterator<Map.Entry<K,V>> iterator() { return new EntryIterator(); } public final boolean contains(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<?,?> e = (Map.Entry<?,?>) o; Object key = e.getKey(); Node<K,V> candidate = getNode(hash(key), key); return candidate != null && candidate.equals(e); } public final boolean remove(Object o) { if (o instanceof Map.Entry) { Map.Entry<?,?> e = (Map.Entry<?,?>) o; Object key = e.getKey(); Object value = e.getValue(); return removeNode(hash(key), key, value, true, true) != null; } return false; } public final Spliterator<Map.Entry<K,V>> spliterator() { return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0); } public final void forEach(Consumer<? super Map.Entry<K,V>> action) { Node<K,V>[] tab; if (action == null) throw new NullPointerException(); if (size > 0 && (tab = table) != null) { int mc = modCount; for (int i = 0; i < tab.length; ++i) { for (Node<K,V> e = tab[i]; e != null; e = e.next) action.accept(e); } if (modCount != mc) throw new ConcurrentModificationException(); } } }}
TreeNode 红黑树部分
参照:http://blog.csdn.net/with_dream/article/details/77012542
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> { TreeNode<K,V> parent; // red-black tree links TreeNode<K,V> left; TreeNode<K,V> right; TreeNode<K,V> prev; // needed to unlink next upon deletion boolean red; TreeNode(int hash, K key, V val, Node<K,V> next) { super(hash, key, val, next); } /** * Returns root of tree containing this node. */ //只有根元素的父节点为null final TreeNode<K,V> root() { for (TreeNode<K,V> r = this, p;;) { if ((p = r.parent) == null) return r; r = p; } } /** * Ensures that the given root is the first node of its bin. */ static <K,V> void moveRootToFront(Node<K,V>[] tab, TreeNode<K,V> root) { int n; if (root != null && tab != null && (n = tab.length) > 0) { int index = (n - 1) & root.hash; TreeNode<K,V> first = (TreeNode<K,V>)tab[index]; if (root != first) { Node<K,V> rn; tab[index] = root; TreeNode<K,V> rp = root.prev; if ((rn = root.next) != null) ((TreeNode<K,V>)rn).prev = rp; if (rp != null) rp.next = rn; if (first != null) first.prev = root; root.next = first; root.prev = null; } assert checkInvariants(root); } } /** * Finds the node starting at root p with the given hash and key. * The kc argument caches comparableClassFor(key) upon first use * comparing keys. */ final TreeNode<K,V> find(int h, Object k, Class<?> kc) { TreeNode<K,V> p = this; do { int ph, dir; K pk; TreeNode<K,V> pl = p.left, pr = p.right, q; if ((ph = p.hash) > h) p = pl; else if (ph < h) p = pr; else if ((pk = p.key) == k || (k != null && k.equals(pk))) return p; else if (pl == null) p = pr; else if (pr == null) p = pl; else if ((kc != null || (kc = comparableClassFor(k)) != null) && (dir = compareComparables(kc, k, pk)) != 0) p = (dir < 0) ? pl : pr; else if ((q = pr.find(h, k, kc)) != null) return q; else p = pl; } while (p != null); return null; } /** * Calls find for root node. */ final TreeNode<K,V> getTreeNode(int h, Object k) { return ((parent != null) ? root() : this).find(h, k, null); } /** * Tie-breaking utility for ordering insertions when equal * hashCodes and non-comparable. We don't require a total * order, just a consistent insertion rule to maintain * equivalence across rebalancings. Tie-breaking further than * necessary simplifies testing a bit. */ static int tieBreakOrder(Object a, Object b) { int d; if (a == null || b == null || (d = a.getClass().getName(). compareTo(b.getClass().getName())) == 0) d = (System.identityHashCode(a) <= System.identityHashCode(b) ? -1 : 1); return d; } /** * Forms tree of the nodes linked from this node. * @return root of tree */ //链表转红黑树 final void treeify(Node<K,V>[] tab) { TreeNode<K,V> root = null; //this为链表首元素 //循环整个链表 for (TreeNode<K,V> x = this, next; x != null; x = next) { next = (TreeNode<K,V>)x.next; x.left = x.right = null; //将第一个元素赋为root if (root == null) { x.parent = null; x.red = false; root = x; } else { K k = x.key; int h = x.hash; Class<?> kc = null; //在红黑树中遍历 for (TreeNode<K,V> p = root;;) { int dir, ph; K pk = p.key; //根据hash判断大小 if ((ph = p.hash) > h) dir = -1; else if (ph < h) dir = 1; else if ((kc == null && (kc = comparableClassFor(k)) == null) || (dir = compareComparables(kc, k, pk)) == 0) dir = tieBreakOrder(k, pk); TreeNode<K,V> xp = p; //插入叶子位置 if ((p = (dir <= 0) ? p.left : p.right) == null) { x.parent = xp; if (dir <= 0) xp.left = x; else xp.right = x; //修正红黑树 root = balanceInsertion(root, x); break; } } } } moveRootToFront(tab, root); } /** * Returns a list of non-TreeNodes replacing those linked from * this node. */ //TreeNode转换为Node final Node<K,V> untreeify(HashMap<K,V> map) { Node<K,V> hd = null, tl = null; for (Node<K,V> q = this; q != null; q = q.next) { Node<K,V> p = map.replacementNode(q, null); if (tl == null) hd = p; else tl.next = p; tl = p; } return hd; } /** * Tree version of putVal. */ //向红黑树插入元素 final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab, int h, K k, V v) { Class<?> kc = null; boolean searched = false; TreeNode<K,V> root = (parent != null) ? root() : this; //遍历 for (TreeNode<K,V> p = root;;) { int dir, ph; K pk; //比较hash值 if ((ph = p.hash) > h) dir = -1; else if (ph < h) dir = 1; //如果键相同 直接返回元素 else if ((pk = p.key) == k || (k != null && k.equals(pk))) return p; //没看懂 else if ((kc == null && (kc = comparableClassFor(k)) == null) || (dir = compareComparables(kc, k, pk)) == 0) { if (!searched) { TreeNode<K,V> q, ch; searched = true; if (((ch = p.left) != null && (q = ch.find(h, k, kc)) != null) || ((ch = p.right) != null && (q = ch.find(h, k, kc)) != null)) return q; } dir = tieBreakOrder(k, pk); } TreeNode<K,V> xp = p; if ((p = (dir <= 0) ? p.left : p.right) == null) { Node<K,V> xpn = xp.next; //新建TreeNode TreeNode<K,V> x = map.newTreeNode(h, k, v, xpn); //追加 if (dir <= 0) xp.left = x; else xp.right = x; xp.next = x; x.parent = x.prev = xp; if (xpn != null) ((TreeNode<K,V>)xpn).prev = x; //调用balanceInsertion插入,并将root放入桶中 moveRootToFront(tab, balanceInsertion(root, x)); return null; } } } /** * Removes the given node, that must be present before this call. * This is messier than typical red-black deletion code because we * cannot swap the contents of an interior node with a leaf * successor that is pinned by "next" pointers that are accessible * independently during traversal. So instead we swap the tree * linkages. If the current tree appears to have too few nodes, * the bin is converted back to a plain bin. (The test triggers * somewhere between 2 and 6 nodes, depending on tree structure). */ final void removeTreeNode(HashMap<K,V> map, Node<K,V>[] tab, boolean movable) { int n; if (tab == null || (n = tab.length) == 0) return; int index = (n - 1) & hash; TreeNode<K,V> first = (TreeNode<K,V>)tab[index], root = first, rl; TreeNode<K,V> succ = (TreeNode<K,V>)next, pred = prev; if (pred == null) tab[index] = first = succ; else pred.next = succ; if (succ != null) succ.prev = pred; if (first == null) return; if (root.parent != null) root = root.root(); if (root == null || root.right == null || (rl = root.left) == null || rl.left == null) { tab[index] = first.untreeify(map); // too small return; } TreeNode<K,V> p = this, pl = left, pr = right, replacement; if (pl != null && pr != null) { TreeNode<K,V> s = pr, sl; while ((sl = s.left) != null) // find successor s = sl; boolean c = s.red; s.red = p.red; p.red = c; // swap colors TreeNode<K,V> sr = s.right; TreeNode<K,V> pp = p.parent; if (s == pr) { // p was s's direct parent p.parent = s; s.right = p; } else { TreeNode<K,V> sp = s.parent; if ((p.parent = sp) != null) { if (s == sp.left) sp.left = p; else sp.right = p; } if ((s.right = pr) != null) pr.parent = s; } p.left = null; if ((p.right = sr) != null) sr.parent = p; if ((s.left = pl) != null) pl.parent = s; if ((s.parent = pp) == null) root = s; else if (p == pp.left) pp.left = s; else pp.right = s; if (sr != null) replacement = sr; else replacement = p; } else if (pl != null) replacement = pl; else if (pr != null) replacement = pr; else replacement = p; if (replacement != p) { TreeNode<K,V> pp = replacement.parent = p.parent; if (pp == null) root = replacement; else if (p == pp.left) pp.left = replacement; else pp.right = replacement; p.left = p.right = p.parent = null; } TreeNode<K,V> r = p.red ? root : balanceDeletion(root, replacement); if (replacement == p) { // detach TreeNode<K,V> pp = p.parent; p.parent = null; if (pp != null) { if (p == pp.left) pp.left = null; else if (p == pp.right) pp.right = null; } } if (movable) moveRootToFront(tab, r); } /** * Splits nodes in a tree bin into lower and upper tree bins, * or untreeifies if now too small. Called only from resize; * see above discussion about split bits and indices. * * @param map the map * @param tab the table for recording bin heads * @param index the index of the table being split * @param bit the bit of hash to split on */ final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) { TreeNode<K,V> b = this; // Relink into lo and hi lists, preserving order TreeNode<K,V> loHead = null, loTail = null; TreeNode<K,V> hiHead = null, hiTail = null; int lc = 0, hc = 0; for (TreeNode<K,V> e = b, next; e != null; e = next) { next = (TreeNode<K,V>)e.next; e.next = null; if ((e.hash & bit) == 0) { if ((e.prev = loTail) == null) loHead = e; else loTail.next = e; loTail = e; ++lc; } else { if ((e.prev = hiTail) == null) hiHead = e; else hiTail.next = e; hiTail = e; ++hc; } } if (loHead != null) { if (lc <= UNTREEIFY_THRESHOLD) tab[index] = loHead.untreeify(map); else { tab[index] = loHead; if (hiHead != null) // (else is already treeified) loHead.treeify(tab); } } if (hiHead != null) { if (hc <= UNTREEIFY_THRESHOLD) tab[index + bit] = hiHead.untreeify(map); else { tab[index + bit] = hiHead; if (loHead != null) hiHead.treeify(tab); } } } /* ------------------------------------------------------------ */ // Red-black tree methods, all adapted from CLR //左旋转 static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root, TreeNode<K,V> p) { TreeNode<K,V> r, pp, rl; if (p != null && (r = p.right) != null) { if ((rl = p.right = r.left) != null) rl.parent = p; if ((pp = r.parent = p.parent) == null) (root = r).red = false; else if (pp.left == p) pp.left = r; else pp.right = r; r.left = p; p.parent = r; } return root; } //右旋转 static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root, TreeNode<K,V> p) { TreeNode<K,V> l, pp, lr; if (p != null && (l = p.left) != null) { if ((lr = p.left = l.right) != null) lr.parent = p; if ((pp = l.parent = p.parent) == null) (root = l).red = false; else if (pp.right == p) pp.right = l; else pp.left = l; l.right = p; p.parent = l; } return root; } //调整红黑树 static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root, TreeNode<K,V> x) { x.red = true; for (TreeNode<K,V> xp, xpp, xppl, xppr;;) { //如果只有一个元素 直接返回 if ((xp = x.parent) == null) { x.red = false; return x; } //如果 else if (!xp.red || (xpp = xp.parent) == null) return root; //一、若“父节点”是“祖父节点的左孩子” if (xp == (xppl = xpp.left)) { //如果叔叔节点是红色 则父节点、叔叔节点都为黑,祖父节点为红 if ((xppr = xpp.right) != null && xppr.red) { xppr.red = false; xp.red = false; xpp.red = true; x = xpp; } else { //如果当前节点为右节点 则左转换 if (x == xp.right) { root = rotateLeft(root, x = xp); xpp = (xp = x.parent) == null ? null : xp.parent; } //右旋转 if (xp != null) { xp.red = false; if (xpp != null) { xpp.red = true; root = rotateRight(root, xpp); } } } } else { if (xppl != null && xppl.red) { xppl.red = false; xp.red = false; xpp.red = true; x = xpp; } else { if (x == xp.left) { root = rotateRight(root, x = xp); xpp = (xp = x.parent) == null ? null : xp.parent; } if (xp != null) { xp.red = false; if (xpp != null) { xpp.red = true; root = rotateLeft(root, xpp); } } } } } } //红黑树的删除操作 static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root, TreeNode<K,V> x) { for (TreeNode<K,V> xp, xpl, xpr;;) { if (x == null || x == root) return root; else if ((xp = x.parent) == null) { x.red = false; return x; } else if (x.red) { x.red = false; return root; } else if ((xpl = xp.left) == x) { if ((xpr = xp.right) != null && xpr.red) { xpr.red = false; xp.red = true; root = rotateLeft(root, xp); xpr = (xp = x.parent) == null ? null : xp.right; } if (xpr == null) x = xp; else { TreeNode<K,V> sl = xpr.left, sr = xpr.right; if ((sr == null || !sr.red) && (sl == null || !sl.red)) { xpr.red = true; x = xp; } else { if (sr == null || !sr.red) { if (sl != null) sl.red = false; xpr.red = true; root = rotateRight(root, xpr); xpr = (xp = x.parent) == null ? null : xp.right; } if (xpr != null) { xpr.red = (xp == null) ? false : xp.red; if ((sr = xpr.right) != null) sr.red = false; } if (xp != null) { xp.red = false; root = rotateLeft(root, xp); } x = root; } } } else { // symmetric if (xpl != null && xpl.red) { xpl.red = false; xp.red = true; root = rotateRight(root, xp); xpl = (xp = x.parent) == null ? null : xp.left; } if (xpl == null) x = xp; else { TreeNode<K,V> sl = xpl.left, sr = xpl.right; if ((sl == null || !sl.red) && (sr == null || !sr.red)) { xpl.red = true; x = xp; } else { if (sl == null || !sl.red) { if (sr != null) sr.red = false; xpl.red = true; root = rotateLeft(root, xpl); xpl = (xp = x.parent) == null ? null : xp.left; } if (xpl != null) { xpl.red = (xp == null) ? false : xp.red; if ((sl = xpl.left) != null) sl.red = false; } if (xp != null) { xp.red = false; root = rotateRight(root, xp); } x = root; } } } } } /** * Recursive invariant check */ static <K,V> boolean checkInvariants(TreeNode<K,V> t) { TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right, tb = t.prev, tn = (TreeNode<K,V>)t.next; if (tb != null && tb.next != t) return false; if (tn != null && tn.prev != t) return false; if (tp != null && t != tp.left && t != tp.right) return false; if (tl != null && (tl.parent != t || tl.hash > t.hash)) return false; if (tr != null && (tr.parent != t || tr.hash < t.hash)) return false; if (t.red && tl != null && tl.red && tr != null && tr.red) return false; if (tl != null && !checkInvariants(tl)) return false; if (tr != null && !checkInvariants(tr)) return false; return true; } }
2.2 主要方法
2.2.1 put
2.3 遍历
public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>(); //使用EntrySet遍历 //如果需要遍历key和set 推荐使用 for (Map.Entry<String, String> entry : map.entrySet()) { entry.getKey(); entry.getValue(); } //迭代器 Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, String> entry = iterator.next(); entry.getKey(); entry.getValue(); } //keySet的到key的集 再foreach //如果只遍历key 推荐使用 for (String key : map.keySet()) { map.get(key); } // Set<Map.Entry<String, String>> entrySet = map.entrySet(); for (Map.Entry<String, String> entry : entrySet) { entry.getKey(); entry.getValue(); } }
3、总结
3.1 HashMap的数据结构为散列表,如果有碰撞,会将碰撞的元素构建为单链表的形式。如果链表长度大于8且容量大于64,会将链表结构转换为红黑树结构。
如果红黑树的个数减小到小于6,则会将红黑树再次转换为链表结构
1.8才有红黑树,之前只是单链表
3.2 HashMap的扩容每次都是原容量*2(在resize中),扩容之后需要重新散列计算位置并赋值,对链表或树进行调整,很消耗性能。所以最好选择一个合适大小的容量
3.3 HashMap的table数组下标为int类型,所以最大可以盛放2^32个数据。但是内存无法盛放如此多的数据,所以计算桶的位置时使用(n - 1) & hash,n为数组的总长度。
n总是2的次方(resize方法中),所以n-1使低n-1位全为1。与上hash可以抹去hash的高位,保证(n - 1) & hash的位置总是落在0~n的范围内
hash值只使用低位,增加了碰撞的几率,所以使用扰动函数即hash方法,使hash值均匀分布
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
参考:https://www.zhihu.com/question/20733617
3.4 HashMap的扩容是根据threshold,threshold=容量*填充因子。当元素个数大于threshold,就会进行扩充。
3.5 HashMap不是线程安全的,如果在多线程下使用需要加锁或者使用线程安全的Map。
https://coolshell.cn/articles/9606.html#more-9606
参考:
http://www.cnblogs.com/skywang12345/p/3310835.html
- HashMap
- HashMap
- HashMap
- HashMap
- HashMap
- HashMap
- HashMap
- HashMap
- HashMap
- HashMap
- HashMap
- hashmap
- HashMap
- HashMap
- HashMap
- hashmap
- HashMap
- Hashmap
- Python中的join()函数的用法
- 我的TI之路
- python—如何使用post进行登录操作与非对称加密的破解
- 从CRP(关键渲染路径)优化中谈浏览器渲染原理
- python 指定版本号
- HashMap
- Mysql动态操作表或者列
- PHP post数据传输部分缺失
- Beginning Spring学习笔记——第4章(一)Spring JDBC连接的配置
- 为什么会觉得无聊?
- Leetcode 56. Merge Intervals
- Beginning Spring学习笔记——第4章(二)使用Spring执行数据访问操作
- Hexo的安装记录
- android动画的学习体会