📄 referencemap.java
字号:
Object makeValueReferenceAware(Object o) { return valueReferenceType == STRONG ? o : new ReferenceAwareWrapper(o); } /** * Dereferences elements in {@code in} using * {@code referenceType} and puts them in {@code out}. Returns * {@code out}. */ <T extends Collection<Object>> T dereferenceCollection( ReferenceType referenceType, T in, T out) { for (Object reference : in) { out.add(dereference(referenceType, reference)); } return out; } /** * Marker interface to differentiate external and internal references. */ interface InternalReference {} static int keyHashCode(Object key) { return System.identityHashCode(key); } /** * Tests weak and soft references for identity equality. Compares references * to other references and wrappers. If o is a reference, this returns true * if r == o or if r and o reference the same non null object. If o is a * wrapper, this returns true if r's referent is identical to the wrapped * object. */ static boolean referenceEquals(Reference r, Object o) { // compare reference to reference. if (o instanceof InternalReference) { // are they the same reference? used in cleanup. if (o == r) { return true; } // do they reference identical values? used in conditional puts. Object referent = ((Reference) o).get(); return referent != null && referent == r.get(); } // is the wrapped object identical to the referent? used in lookups. return ((ReferenceAwareWrapper) o).unwrap() == r.get(); } /** * Big hack. Used to compare keys and values to referenced keys and values * without creating more references. */ static class ReferenceAwareWrapper { Object wrapped; ReferenceAwareWrapper(Object wrapped) { this.wrapped = wrapped; } Object unwrap() { return wrapped; } public int hashCode() { return wrapped.hashCode(); } public boolean equals(Object obj) { // defer to reference's equals() logic. return obj.equals(this); } } /** * Used for keys. Overrides hash code to use identity hash code. */ static class KeyReferenceAwareWrapper extends ReferenceAwareWrapper { public KeyReferenceAwareWrapper(Object wrapped) { super(wrapped); } public int hashCode() { return System.identityHashCode(wrapped); } } class SoftKeyReference extends FinalizableSoftReference<Object> implements InternalReference { int hashCode; public SoftKeyReference(Object key) { super(key); this.hashCode = keyHashCode(key); } public void finalizeReferent() { delegate.remove(this); } @Override public int hashCode() { return this.hashCode; } @Override public boolean equals(Object o) { return referenceEquals(this, o); } } class WeakKeyReference extends FinalizableWeakReference<Object> implements InternalReference { int hashCode; public WeakKeyReference(Object key) { super(key); this.hashCode = keyHashCode(key); } public void finalizeReferent() { delegate.remove(this); } @Override public int hashCode() { return this.hashCode; } @Override public boolean equals(Object o) { return referenceEquals(this, o); } } class SoftValueReference extends FinalizableSoftReference<Object> implements InternalReference { Object keyReference; public SoftValueReference(Object keyReference, Object value) { super(value); this.keyReference = keyReference; } public void finalizeReferent() { delegate.remove(keyReference, this); } @Override public boolean equals(Object obj) { return referenceEquals(this, obj); } } class WeakValueReference extends FinalizableWeakReference<Object> implements InternalReference { Object keyReference; public WeakValueReference(Object keyReference, Object value) { super(value); this.keyReference = keyReference; } public void finalizeReferent() { delegate.remove(keyReference, this); } @Override public boolean equals(Object obj) { return referenceEquals(this, obj); } } protected interface Strategy { public Object execute(ReferenceMap map, Object keyReference, Object valueReference); } protected Strategy putStrategy() { return PutStrategy.PUT; } protected Strategy putIfAbsentStrategy() { return PutStrategy.PUT_IF_ABSENT; } protected Strategy replaceStrategy() { return PutStrategy.REPLACE; } private enum PutStrategy implements Strategy { PUT { public Object execute(ReferenceMap map, Object keyReference, Object valueReference) { return map.delegate.put(keyReference, valueReference); } }, REPLACE { public Object execute(ReferenceMap map, Object keyReference, Object valueReference) { return map.delegate.replace(keyReference, valueReference); } }, PUT_IF_ABSENT { public Object execute(ReferenceMap map, Object keyReference, Object valueReference) { return map.delegate.putIfAbsent(keyReference, valueReference); } }; }; private static PutStrategy defaultPutStrategy; protected PutStrategy getPutStrategy() { return defaultPutStrategy; } class Entry implements Map.Entry<K, V> { K key; V value; public Entry(K key, V value) { this.key = key; this.value = value; } public K getKey() { return this.key; } public V getValue() { return this.value; } public V setValue(V value) { return put(key, value); } public int hashCode() { return key.hashCode() * 31 + value.hashCode(); } public boolean equals(Object o) { if (!(o instanceof ReferenceMap.Entry)) { return false; } Entry entry = (Entry) o; return key.equals(entry.key) && value.equals(entry.value); } public String toString() { return key + "=" + value; } } static void ensureNotNull(Object o) { if (o == null) { throw new NullPointerException(); } } static void ensureNotNull(Object... array) { for (int i = 0; i < array.length; i++) { if (array[i] == null) { throw new NullPointerException("Argument #" + i + " is null."); } } } private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeInt(size()); for (Map.Entry<Object, Object> entry : delegate.entrySet()) { Object key = dereferenceKey(entry.getKey()); Object value = dereferenceValue(entry.getValue()); // don't persist gc'ed entries. if (key != null && value != null) { out.writeObject(key); out.writeObject(value); } } out.writeObject(null); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); int size = in.readInt(); this.delegate = new ConcurrentHashMap<Object, Object>(size); while (true) { K key = (K) in.readObject(); if (key == null) { break; } V value = (V) in.readObject(); put(key, value); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -