Java集合之WeakHashMap
--陆游 问渠那得清如许,为有源头活水来 --朱熹
void clear()
Object clone()
boolean containsKey(Object key)
boolean containsValue(Object value)
Set<Entry<K, V>> entrySet()
V get(Object key)
boolean isEmpty()
Set<K> keySet()
V put(K key, V value)
void putAll(Map<? extends K, ? extends V> map)
V remove(Object key)
int size()
Collection<V> values()
WeakHashMap的遍历方式
Integer integ = null;
Iterator iter = map.entrySet().iterator();
while(iter.hasNext())
{
Map.Entry entry = (Map.Entry)iter.next();
// 获取key
key = (String)entry.getKey();
// 获取value
integ = (Integer)entry.getValue();
}
(2)遍历WeakHashMap的键:首先通过keySet()获取WeakHashMap的键的set集合,通过Iterator迭代器遍历集合来获得键值。
String key = null;
Integer integ = null;
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
// 获取key
key = (String)iter.next();
// 根据key,获取value
integ = (Integer)map.get(key);
}
(3)遍历WeakHashMap的值:首先通过values()获取WeakHashMap的value集合,然后对集合进行迭代获得数据。
Integer value = null;
Collection c = map.values();
Iterator iter= c.iterator();
while (iter.hasNext())
{
value = (Integer)iter.next();
}
WeakHashMap示例程序:
public class Hello { public static void main(String[] args) throws Exception { testWeakHashMapAPIs(); } private static void testWeakHashMapAPIs() { // 初始化3个“弱键” String w1 = new String("one"); String w2 = new String("two"); String w3 = new String("three"); // 新建WeakHashMap Map wmap = new WeakHashMap(); // 添加键值对 wmap.put(w1, "w1"); wmap.put(w2, "w2"); wmap.put(w3, "w3"); // 打印出wmap System.out.printf("\nwmap:%s\n",wmap ); // containsKey(Object key) :是否包含键key System.out.printf("contains key two : %s\n",wmap.containsKey("two")); System.out.printf("contains key five : %s\n",wmap.containsKey("five")); // containsValue(Object value) :是否包含值value ))); // remove(Object key) : 删除键key对应的键值对 wmap.remove("three"); System.out.printf("wmap: %s\n",wmap ); // ---- 测试 WeakHashMap 的自动回收特性 ---- // 将w1设置null。 // 这意味着“弱键”w1再没有被其它对象引用,调用gc时会回收WeakHashMap中与“w1”对应的键值对 w1 = null; // 内存回收。这里,会回收WeakHashMap中与“w1”对应的键值对 System.gc(); // 遍历WeakHashMap Iterator iter = wmap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry en = (Map.Entry)iter.next(); System.out.printf("next : %s - %s\n",en.getKey(),en.getValue()); } // 打印WeakHashMap的实际大小 System.out.printf(" after gc WeakHashMap size:%s\n", wmap.size()); } }
public class WeakHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V> { ;//默认初始大小,必须是2的次幂 ;//最大值2的30次方 private static final float DEFAULT_LOAD_FACTOR = 0.75f;//加载因子 Entry<K,V>[] table; private int size;//数目 private int threshold;//阈值 private final float loadFactor;//加载因子 private final ReferenceQueue<Object> queue = new ReferenceQueue<>();//引用队列 int modCount;//fail-fast @SuppressWarnings("unchecked") private Entry<K,V>[] newTable(int n) { return (Entry<K,V>[]) new Entry<?,?>[n]; } //构造函数 public WeakHashMap(int initialCapacity, float loadFactor) { ) 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); ; while (capacity < initialCapacity) capacity <<= ; table = newTable(capacity); this.loadFactor = loadFactor; threshold = (int)(capacity * loadFactor); } //初始值的构造函数 public WeakHashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } //构造函数 public WeakHashMap() { this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); } public WeakHashMap(Map<? extends K, ? extends V> m) { , DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); putAll(m); } // internal utilities /** * Value representing null keys inside tables. */ private static final Object NULL_KEY = new Object(); /** * Use NULL_KEY for key if it is null. */ private static Object maskNull(Object key) { return (key == null) ? NULL_KEY : key; } /** * Returns internal representation of null key back to caller as null. */ static Object unmaskNull(Object key) { return (key == NULL_KEY) ? null : key; } /** * Checks for equality of non-null reference x and possibly-null y. By * default uses Object.equals. */ private static boolean eq(Object x, Object y) { return x == y || x.equals(y); } /** * Retrieve object hash code and applies a supplemental hash function to the * result hash, which defends against poor quality hash functions. This is * critical because HashMap uses power-of-two length hash tables, that * otherwise encounter collisions for hashCodes that do not differ * in lower bits. */ //计算k的hash final int hash(Object k) { int h = k.hashCode(); // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). ) ^ (h >>> ); ) ^ (h >>> ); } /** * Returns index for hash code h. */ private static int indexFor(int h, int length) { ); } /** * Expunges stale entries from the table. */ private void expungeStaleEntries() { for (Object x; (x = queue.poll()) != null; ) { synchronized (queue) { @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>) x; int i = indexFor(e.hash, table.length); Entry<K,V> prev = table[i]; Entry<K,V> p = prev; while (p != null) { Entry<K,V> next = p.next; if (p == e) { if (prev == e) table[i] = next; else prev.next = next; // Must not null out e.next; // stale entries may be in use by a HashIterator e.value = null; // Help GC size--; break; } prev = p; p = next; } } } } /** * Returns the table after first expunging stale entries. */ private Entry<K,V>[] getTable() { expungeStaleEntries(); return table; } /** * Returns the number of key-value mappings in this map. * This result is a snapshot, and may not reflect unprocessed * entries that will be removed before next attempted access * because they are no longer referenced. */ //返回数目 public int size() { ) ; expungeStaleEntries(); return size; } /** * Returns <tt>true</tt> if this map contains no key-value mappings. * This result is a snapshot, and may not reflect unprocessed * entries that will be removed before next attempted access * because they are no longer referenced. */ //判断是否为空 public boolean isEmpty() { ; } /** * Returns the value to which the specified key is mapped, * or {@code null} if this map contains no mapping for the key. * * <p>More formally, if this map contains a mapping from a key * {@code k} to a value {@code v} such that {@code (key==null ? k==null : * key.equals(k))}, then this method returns {@code v}; otherwise * it returns {@code null}. (There can be at most one such mapping.) * * <p>A return value of {@code null} does not <i>necessarily</i> * indicate that the map contains no mapping for the key; it's also * possible that the map explicitly maps the key to {@code null}. * The {@link #containsKey containsKey} operation may be used to * distinguish these two cases. * * @see #put(Object, Object) */ //通过key获得value public V get(Object key) { Object k = maskNull(key); int h = hash(k); Entry<K,V>[] tab = getTable(); int index = indexFor(h, tab.length); Entry<K,V> e = tab[index]; while (e != null) { if (e.hash == h && eq(k, e.get())) return e.value; e = e.next; } return null; } /** * Returns <tt>true</tt> if this map contains a mapping for the * specified key. * * @param key The key whose presence in this map is to be tested * @return <tt>true</tt> if there is a mapping for <tt>key</tt>; * <tt>false</tt> otherwise */ //判断是否包含某个key public boolean containsKey(Object key) { return getEntry(key) != null; } /** * Returns the entry associated with the specified key in this map. * Returns null if the map contains no mapping for this key. */ //通过key获得entry Entry<K,V> getEntry(Object key) { Object k = maskNull(key); int h = hash(k); Entry<K,V>[] tab = getTable(); int index = indexFor(h, tab.length); Entry<K,V> e = tab[index]; while (e != null && !(e.hash == h && eq(k, e.get()))) e = e.next; return e; } /** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for this key, the old * value is replaced. * * @param key key with which the specified value is to be associated. * @param value value to be associated with the specified key. * @return the previous value associated with <tt>key</tt>, or * <tt>null</tt> if there was no mapping for <tt>key</tt>. * (A <tt>null</tt> return can also indicate that the map * previously associated <tt>null</tt> with <tt>key</tt>.) */ //插入key和value public V put(K key, V value) { Object k = maskNull(key); int h = hash(k); Entry<K,V>[] tab = getTable(); int i = indexFor(h, tab.length); for (Entry<K,V> e = tab[i]; e != null; e = e.next) { if (h == e.hash && eq(k, e.get())) { V oldValue = e.value; if (value != oldValue) e.value = value; return oldValue; } } modCount++; Entry<K,V> e = tab[i]; tab[i] = new Entry<>(k, value, queue, h, e); if (++size >= threshold) resize(tab.); return null; } /** * Rehashes the contents of this map into a new array with a * larger capacity. This method is called automatically when the * number of keys in this map reaches its threshold. * * If current capacity is MAXIMUM_CAPACITY, this method does not * resize the map, but sets threshold to Integer.MAX_VALUE. * This has the effect of preventing future calls. * * @param newCapacity the new capacity, MUST be a power of two; * must be greater than current capacity unless current * capacity is MAXIMUM_CAPACITY (in which case value * is irrelevant). */ //跳转大小 void resize(int newCapacity) { Entry<K,V>[] oldTable = getTable(); int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return; } Entry<K,V>[] newTable = newTable(newCapacity); transfer(oldTable, newTable); table = newTable; /* * If ignoring null elements and processing ref queue caused massive * shrinkage, then restore old table. This should be rare, but avoids * unbounded expansion of garbage-filled tables. */ ) { threshold = (int)(newCapacity * loadFactor); } else { expungeStaleEntries(); transfer(newTable, oldTable); table = oldTable; } } /** Transfers all entries from src to dest tables */ private void transfer(Entry<K,V>[] src, Entry<K,V>[] dest) { ; j < src.length; ++j) { Entry<K,V> e = src[j]; src[j] = null; while (e != null) { Entry<K,V> next = e.next; Object key = e.get(); if (key == null) { e.next = null; // Help GC e.value = null; // " " size--; } else { int i = indexFor(e.hash, dest.length); e.next = dest[i]; dest[i] = e; } e = next; } } } /** * Copies all of the mappings from the specified map to this map. * These mappings will replace any mappings that this map had for any * of the keys currently in the specified map. * * @param m mappings to be stored in this map. * @throws NullPointerException if the specified map is null. */ public void putAll(Map<? extends K, ? extends V> m) { int numKeysToBeAdded = m.size(); ) return; /* * Expand the map if the map if the number of mappings to be added * is greater than or equal to threshold. This is conservative; the * obvious condition is (m.size() + size) >= threshold, but this * condition could result in a map with twice the appropriate capacity, * if the keys to be added overlap with the keys already in this map. * By using the conservative calculation, we subject ourself * to at most one extra resize. */ if (numKeysToBeAdded > threshold) { ); if (targetCapacity > MAXIMUM_CAPACITY) targetCapacity = MAXIMUM_CAPACITY; int newCapacity = table.length; while (newCapacity < targetCapacity) newCapacity <<= ; if (newCapacity > table.length) resize(newCapacity); } for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) put(e.getKey(), e.getValue()); } /** * Removes the mapping for a key from this weak hash map if it is present. * More formally, if this map contains a mapping from key <tt>k</tt> to * value <tt>v</tt> such that <code>(key==null ? k==null : * key.equals(k))</code>, that mapping is removed. (The map can contain * at most one such mapping.) * * <p>Returns the value to which this map previously associated the key, * or <tt>null</tt> if the map contained no mapping for the key. A * return value of <tt>null</tt> does not <i>necessarily</i> indicate * that the map contained no mapping for the key; it's also possible * that the map explicitly mapped the key to <tt>null</tt>. * * <p>The map will not contain a mapping for the specified key once the * call returns. * * @param key key whose mapping is to be removed from the map * @return the previous value associated with <tt>key</tt>, or * <tt>null</tt> if there was no mapping for <tt>key</tt> */ //根据key删除 public V remove(Object key) { Object k = maskNull(key); int h = hash(k); Entry<K,V>[] tab = getTable(); int i = indexFor(h, tab.length); Entry<K,V> prev = tab[i]; Entry<K,V> e = prev; while (e != null) { Entry<K,V> next = e.next; if (h == e.hash && eq(k, e.get())) { modCount++; size--; if (prev == e) tab[i] = next; else prev.next = next; return e.value; } prev = e; e = next; } return null; } /** Special version of remove needed by Entry set */ boolean removeMapping(Object o) { if (!(o instanceof Map.Entry)) return false; Entry<K,V>[] tab = getTable(); Map.Entry<?,?> entry = (Map.Entry<?,?>)o; Object k = maskNull(entry.getKey()); int h = hash(k); int i = indexFor(h, tab.length); Entry<K,V> prev = tab[i]; Entry<K,V> e = prev; while (e != null) { Entry<K,V> next = e.next; if (h == e.hash && e.equals(entry)) { modCount++; size--; if (prev == e) tab[i] = next; else prev.next = next; return true; } prev = e; e = next; } return false; } /** * Removes all of the mappings from this map. * The map will be empty after this call returns. */ //清空 public void clear() { // clear out ref queue. We don't need to expunge entries // since table is getting cleared. while (queue.poll() != null) ; modCount++; Arrays.fill(table, null); ; // Allocation of array may have caused GC, which may have caused // additional entries to go stale. Removing these entries from the // reference queue will make them eligible for reclamation. while (queue.poll() != null) ; } /** * Returns <tt>true</tt> if this map maps one or more keys to the * specified value. * * @param value value whose presence in this map is to be tested * @return <tt>true</tt> if this map maps one or more keys to the * specified value */ //判断是否包含某个值 public boolean containsValue(Object value) { if (value==null) return containsNullValue(); Entry<K,V>[] tab = getTable(); ;) for (Entry<K,V> e = tab[i]; e != null; e = e.next) if (value.equals(e.value)) return true; return false; } /** * Special-case code for containsValue with null argument */ //判断是否有空值 private boolean containsNullValue() { Entry<K,V>[] tab = getTable(); ;) for (Entry<K,V> e = tab[i]; e != null; e = e.next) if (e.value==null) return true; return false; } /** * The entries in this hash table extend WeakReference, using its main ref * field as the key. */ //entry继承了虚引用 private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> { V value; final int hash; Entry<K,V> next; /** * Creates new entry. */ Entry(Object key, V value, ReferenceQueue<Object> queue, int hash, Entry<K,V> next) { super(key, queue); this.value = value; this.hash = hash; this.next = next; } @SuppressWarnings("unchecked") public K getKey() { return (K) WeakHashMap.unmaskNull(get()); } public V getValue() { return value; } public V setValue(V newValue) { V oldValue = value; value = newValue; return oldValue; } public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<?,?> e = (Map.Entry<?,?>)o; K k1 = getKey(); Object k2 = e.getKey(); if (k1 == k2 || (k1 != null && k1.equals(k2))) { V v1 = getValue(); Object v2 = e.getValue(); if (v1 == v2 || (v1 != null && v1.equals(v2))) return true; } return false; } public int hashCode() { K k = getKey(); V v = getValue(); return Objects.hashCode(k) ^ Objects.hashCode(v); } public String toString() { return getKey() + "=" + getValue(); } } private abstract class HashIterator<T> implements Iterator<T> { private int index; private Entry<K,V> entry; private Entry<K,V> lastReturned; private int expectedModCount = modCount; /** * Strong reference needed to avoid disappearance of key * between hasNext and next */ private Object nextKey; /** * Strong reference needed to avoid disappearance of key * between nextEntry() and any use of the entry */ private Object currentKey; HashIterator() { index = isEmpty() ? 0 : table.length; } public boolean hasNext() { Entry<K,V>[] t = table; while (nextKey == null) { Entry<K,V> e = entry; int i = index; ) e = t[--i]; entry = e; index = i; if (e == null) { currentKey = null; return false; } nextKey = e.get(); // hold on to key in strong ref if (nextKey == null) entry = entry.next; } return true; } /** The common parts of next() across different types of iterators */ protected Entry<K,V> nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (nextKey == null && !hasNext()) throw new NoSuchElementException(); lastReturned = entry; entry = entry.next; currentKey = nextKey; nextKey = null; return lastReturned; } public void remove() { if (lastReturned == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); WeakHashMap.this.remove(currentKey); expectedModCount = modCount; lastReturned = null; currentKey = null; } } private class ValueIterator extends HashIterator<V> { public V next() { return nextEntry().value; } } private class KeyIterator extends HashIterator<K> { public K next() { return nextEntry().getKey(); } } private class EntryIterator extends HashIterator<Map.Entry<K,V>> { public Map.Entry<K,V> next() { return nextEntry(); } } // Views private transient Set<Map.Entry<K,V>> entrySet; /** * Returns a {@link Set} view of the keys contained in this map. * The set is backed by the map, so changes to the map are * reflected in the set, and vice-versa. If the map is modified * while an iteration over the set is in progress (except through * the iterator's own <tt>remove</tt> operation), the results of * the iteration are undefined. The set supports element removal, * which removes the corresponding mapping from the map, via the * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> * operations. It does not support the <tt>add</tt> or <tt>addAll</tt> * operations. */ public Set<K> keySet() { Set<K> ks = keySet; return (ks != null ? ks : (keySet = new KeySet())); } private class KeySet extends AbstractSet<K> { public Iterator<K> iterator() { return new KeyIterator(); } public int size() { return WeakHashMap.this.size(); } public boolean contains(Object o) { return containsKey(o); } public boolean remove(Object o) { if (containsKey(o)) { WeakHashMap.this.remove(o); return true; } else return false; } public void clear() { WeakHashMap.this.clear(); } public Spliterator<K> spliterator() { ); } } /** * Returns a {@link Collection} view of the values contained in this map. * The collection is backed by the map, so changes to the map are * reflected in the collection, and vice-versa. If the map is * modified while an iteration over the collection is in progress * (except through the iterator's own <tt>remove</tt> operation), * the results of the iteration are undefined. The collection * supports element removal, which removes the corresponding * mapping from the map, via the <tt>Iterator.remove</tt>, * <tt>Collection.remove</tt>, <tt>removeAll</tt>, * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not * support the <tt>add</tt> or <tt>addAll</tt> operations. */ public Collection<V> values() { Collection<V> vs = values; return (vs != null) ? vs : (values = new Values()); } private class Values extends AbstractCollection<V> { public Iterator<V> iterator() { return new ValueIterator(); } public int size() { return WeakHashMap.this.size(); } public boolean contains(Object o) { return containsValue(o); } public void clear() { WeakHashMap.this.clear(); } public Spliterator<V> spliterator() { ); } } /** * Returns a {@link Set} view of the mappings contained in this map. * The set is backed by the map, so changes to the map are * reflected in the set, and vice-versa. If the map is modified * while an iteration over the set is in progress (except through * the iterator's own <tt>remove</tt> operation, or through the * <tt>setValue</tt> operation on a map entry returned by the * iterator) the results of the iteration are undefined. The set * supports element removal, which removes the corresponding * mapping from the map, via the <tt>Iterator.remove</tt>, * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and * <tt>clear</tt> operations. It does not support the * <tt>add</tt> or <tt>addAll</tt> operations. */ public Set<Map.Entry<K,V>> entrySet() { Set<Map.Entry<K,V>> es = entrySet; return es != null ? es : (entrySet = new EntrySet()); } private class EntrySet extends AbstractSet<Map.Entry<K,V>> { public Iterator<Map.Entry<K,V>> iterator() { return new EntryIterator(); } public boolean contains(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<?,?> e = (Map.Entry<?,?>)o; Entry<K,V> candidate = getEntry(e.getKey()); return candidate != null && candidate.equals(e); } public boolean remove(Object o) { return removeMapping(o); } public int size() { return WeakHashMap.this.size(); } public void clear() { WeakHashMap.this.clear(); } private List<Map.Entry<K,V>> deepCopy() { List<Map.Entry<K,V>> list = new ArrayList<>(size()); for (Map.Entry<K,V> e : this) list.add(new AbstractMap.SimpleEntry<>(e)); return list; } public Object[] toArray() { return deepCopy().toArray(); } public <T> T[] toArray(T[] a) { return deepCopy().toArray(a); } public Spliterator<Map.Entry<K,V>> spliterator() { ); } } @SuppressWarnings("unchecked") @Override public void forEach(BiConsumer<? super K, ? super V> action) { Objects.requireNonNull(action); int expectedModCount = modCount; Entry<K, V>[] tab = getTable(); for (Entry<K, V> entry : tab) { while (entry != null) { Object key = entry.get(); if (key != null) { action.accept((K)WeakHashMap.unmaskNull(key), entry.value); } entry = entry.next; if (expectedModCount != modCount) { throw new ConcurrentModificationException(); } } } } @SuppressWarnings("unchecked") @Override public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { Objects.requireNonNull(function); int expectedModCount = modCount; Entry<K, V>[] tab = getTable();; for (Entry<K, V> entry : tab) { while (entry != null) { Object key = entry.get(); if (key != null) { entry.value = function.apply((K)WeakHashMap.unmaskNull(key), entry.value); } entry = entry.next; if (expectedModCount != modCount) { throw new ConcurrentModificationException(); } } } } /** * Similar form as other hash Spliterators, but skips dead * elements. */ static class WeakHashMapSpliterator<K,V> { final WeakHashMap<K,V> map; WeakHashMap.Entry<K,V> current; // current node int index; // current index, modified on advance/split int fence; // -1 until first use; then one past last index int est; // size estimate int expectedModCount; // for comodification checks WeakHashMapSpliterator(WeakHashMap<K,V> m, int origin, int fence, int est, int expectedModCount) { this.map = m; this.index = origin; this.fence = fence; this.est = est; this.expectedModCount = expectedModCount; } final int getFence() { // initialize fence and size on first use int hi; ) { WeakHashMap<K,V> m = map; est = m.size(); expectedModCount = m.modCount; hi = fence = m.table.length; } return hi; } public final long estimateSize() { getFence(); // force init return (long) est; } } static final class KeySpliterator<K,V> extends WeakHashMapSpliterator<K,V> implements Spliterator<K> { KeySpliterator(WeakHashMap<K,V> m, int origin, int fence, int est, int expectedModCount) { super(m, origin, fence, est, expectedModCount); } public KeySpliterator<K,V> trySplit() { ; return (lo >= mid) ? null : , expectedModCount); } public void forEachRemaining(Consumer<? super K> action) { int i, hi, mc; if (action == null) throw new NullPointerException(); WeakHashMap<K,V> m = map; WeakHashMap.Entry<K,V>[] tab = m.table; ) { mc = expectedModCount = m.modCount; hi = fence = tab.length; } else mc = expectedModCount; if (tab.length >= hi && (i = index) >= 0 && (i < (index = hi) || current != null)) { WeakHashMap.Entry<K,V> p = current; current = null; // exhaust do { if (p == null) p = tab[i++]; else { Object x = p.get(); p = p.next; if (x != null) { @SuppressWarnings("unchecked") K k = (K) WeakHashMap.unmaskNull(x); action.accept(k); } } } while (p != null || i < hi); } if (m.modCount != mc) throw new ConcurrentModificationException(); } public boolean tryAdvance(Consumer<? super K> action) { int hi; if (action == null) throw new NullPointerException(); WeakHashMap.Entry<K,V>[] tab = map.table; ) { while (current != null || index < hi) { if (current == null) current = tab[index++]; else { Object x = current.get(); current = current.next; if (x != null) { @SuppressWarnings("unchecked") K k = (K) WeakHashMap.unmaskNull(x); action.accept(k); if (map.modCount != expectedModCount) throw new ConcurrentModificationException(); return true; } } } } return false; } public int characteristics() { return Spliterator.DISTINCT; } } static final class ValueSpliterator<K,V> extends WeakHashMapSpliterator<K,V> implements Spliterator<V> { ValueSpliterator(WeakHashMap<K,V> m, int origin, int fence, int est, int expectedModCount) { super(m, origin, fence, est, expectedModCount); } public ValueSpliterator<K,V> trySplit() { ; return (lo >= mid) ? null : , expectedModCount); } public void forEachRemaining(Consumer<? super V> action) { int i, hi, mc; if (action == null) throw new NullPointerException(); WeakHashMap<K,V> m = map; WeakHashMap.Entry<K,V>[] tab = m.table; ) { mc = expectedModCount = m.modCount; hi = fence = tab.length; } else mc = expectedModCount; if (tab.length >= hi && (i = index) >= 0 && (i < (index = hi) || current != null)) { WeakHashMap.Entry<K,V> p = current; current = null; // exhaust do { if (p == null) p = tab[i++]; else { Object x = p.get(); V v = p.value; p = p.next; if (x != null) action.accept(v); } } while (p != null || i < hi); } if (m.modCount != mc) throw new ConcurrentModificationException(); } public boolean tryAdvance(Consumer<? super V> action) { int hi; if (action == null) throw new NullPointerException(); WeakHashMap.Entry<K,V>[] tab = map.table; ) { while (current != null || index < hi) { if (current == null) current = tab[index++]; else { Object x = current.get(); V v = current.value; current = current.next; if (x != null) { action.accept(v); if (map.modCount != expectedModCount) throw new ConcurrentModificationException(); return true; } } } } return false; } public int characteristics() { ; } } static final class EntrySpliterator<K,V> extends WeakHashMapSpliterator<K,V> implements Spliterator<Map.Entry<K,V>> { EntrySpliterator(WeakHashMap<K,V> m, int origin, int fence, int est, int expectedModCount) { super(m, origin, fence, est, expectedModCount); } public EntrySpliterator<K,V> trySplit() { ; return (lo >= mid) ? null : , expectedModCount); } public void forEachRemaining(Consumer<? super Map.Entry<K, V>> action) { int i, hi, mc; if (action == null) throw new NullPointerException(); WeakHashMap<K,V> m = map; WeakHashMap.Entry<K,V>[] tab = m.table; ) { mc = expectedModCount = m.modCount; hi = fence = tab.length; } else mc = expectedModCount; if (tab.length >= hi && (i = index) >= 0 && (i < (index = hi) || current != null)) { WeakHashMap.Entry<K,V> p = current; current = null; // exhaust do { if (p == null) p = tab[i++]; else { Object x = p.get(); V v = p.value; p = p.next; if (x != null) { @SuppressWarnings("unchecked") K k = (K) WeakHashMap.unmaskNull(x); action.accept (new AbstractMap.SimpleImmutableEntry<K,V>(k, v)); } } } while (p != null || i < hi); } if (m.modCount != mc) throw new ConcurrentModificationException(); } public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) { int hi; if (action == null) throw new NullPointerException(); WeakHashMap.Entry<K,V>[] tab = map.table; ) { while (current != null || index < hi) { if (current == null) current = tab[index++]; else { Object x = current.get(); V v = current.value; current = current.next; if (x != null) { @SuppressWarnings("unchecked") K k = (K) WeakHashMap.unmaskNull(x); action.accept (new AbstractMap.SimpleImmutableEntry<K,V>(k, v)); if (map.modCount != expectedModCount) throw new ConcurrentModificationException(); return true; } } } } return false; } public int characteristics() { return Spliterator.DISTINCT; } } }
Java集合之WeakHashMap的更多相关文章
- 死磕 java集合之WeakHashMap源码分析
欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 简介 WeakHashMap是一种弱引用map,内部的key会存储为弱引用,当jvm gc的时 ...
- 死磕 java集合之终结篇
概览 我们先来看一看java中所有集合的类关系图. 这里面的类太多了,请放大看,如果放大还看不清,请再放大看,如果还是看不清,请放弃. 我们下面主要分成五个部分来逐个击破. List List中的元素 ...
- Java 集合系列14之 Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)
概要 学完了Map的全部内容,我们再回头开开Map的框架图. 本章内容包括:第1部分 Map概括第2部分 HashMap和Hashtable异同第3部分 HashMap和WeakHashMap异同 转 ...
- Java 集合系列 13 WeakHashMap
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- Java 集合 持有引用 & WeakHashMap
Java 集合 持有引用 & WeakHashMap @author ixenos 摘要:强引用.弱引用.WeakHashMap动态回收步骤 Reference引用对象 可获得的(reacha ...
- Java集合框架List,Map,Set等全面介绍
Java集合框架的基本接口/类层次结构: java.util.Collection [I]+--java.util.List [I] +--java.util.ArrayList [C] +- ...
- Java 集合框架
Java集合框架大致可以分为五个部分:List列表,Set集合.Map映射.迭代器.工具类 List 接口通常表示一个列表(数组.队列.链表 栈),其中的元素 可以重复 的是:ArrayList 和L ...
- Java 集合系列目录(Category)
下面是最近总结的Java集合(JDK1.6.0_45)相关文章的目录. 01. Java 集合系列01之 总体框架 02. Java 集合系列02之 Collection架构 03. Java 集合系 ...
- Java集合源码分析(一)
Java集合工具包位于Java.util包下,包含了很多常用的数据结构,如数组.链表.栈.队列.集合.哈希表等.学习Java集合框架下大致可以分为如下五个部分:List列表.Set集合.Map映射.迭 ...
随机推荐
- NLP系列(5)_从朴素贝叶斯到N-gram语言模型
作者: 龙心尘 && 寒小阳 时间:2016年2月. 出处: http://blog.csdn.net/longxinchen_ml/article/details/50646528 ...
- Matplotlib Toolkits:地图绘制工具
Matplotlib Toolkits:地图绘制工具 有没有一种可以直接在详细地图(如谷歌地图)上绘制上百万坐标点的工具???谷歌地图坐标点多了也不能绘制了. Basemap (Not distrib ...
- Android源码浅析(六)——SecureCRT远程连接Linux,配置端点和字节码
Android源码浅析(六)--SecureCRT远程连接Linux,配置端点和字节码 需要编译源码的同学,一般都是win+虚拟机吧,但是再虚拟机里体验并不是很好,所有市面上有很多的软件能够做到在wi ...
- Django 是如何实现用户登录和登出机制的(默认版本-数据库版本)
Django session 字典,保存到数据库的时候是要先序列化的(session.encode方法), 读取的时候反序列化(session.decode),这样比较安全. 一 settings.p ...
- RxJava操作符(08-条件和布尔操作)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51671826 本文出自:[openXu的博客] 目录: All Amb Contains D ...
- RxJava操作符(07-辅助操作)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51658445 本文出自:[openXu的博客] 目录: Delay Do Materiali ...
- ViewPager 几个状态详解
ViewPager.SCROLL_STATE_DRAGGING 当用户按下ViewPager视图并且需要滑动第一下时; ViewPager.SCROLL_STATE_SETTLING: 当用户滑动的放 ...
- LATEX TEMPLATE (SPRINGER) (*.BST)
该模板在哪里下载? http://www.springer.com/computer/image+processing/journal/11263, Instructions for Authors, ...
- Python读取JSON数据,并解决字符集不匹配问题
今天来谈一谈Python解析JSON数据,并写入到本地文件的一个小例子. – 思路如下 从一个返回JSON天气数据的网站获取到目标JSON数据串 使用Python解析出需要的部分 写入到本地文件,供其 ...
- UNIX网络编程——利用recv和readn函数实现readline函数
在前面的文章中,我们为了避免粘包问题,实现了一个readn函数读取固定字节的数据.如果应用层协议的各字段长度固定,用readn来读是非常方便的.例如设计一种客户端上传文件的协议,规定前12字节表示文件 ...