diff options
author | Andy Clement <aclement@pivotal.io> | 2017-09-28 15:52:29 -0700 |
---|---|---|
committer | Andy Clement <aclement@pivotal.io> | 2017-09-28 15:52:29 -0700 |
commit | b7e4aff1c15a0984d4ca772ffb82cdd9b0f6fa57 (patch) | |
tree | 7ddb1bc03335301416c9f66ed1a31fa69376ccbe /util | |
parent | 50422cb5dece5859f5f2bff3027bfa33d8bf4cde (diff) | |
download | aspectj-b7e4aff1c15a0984d4ca772ffb82cdd9b0f6fa57.tar.gz aspectj-b7e4aff1c15a0984d4ca772ffb82cdd9b0f6fa57.zip |
Reusable SoftHashMap utility class
Diffstat (limited to 'util')
-rw-r--r-- | util/src/org/aspectj/util/SoftHashMap.java | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/util/src/org/aspectj/util/SoftHashMap.java b/util/src/org/aspectj/util/SoftHashMap.java new file mode 100644 index 000000000..f7971bddb --- /dev/null +++ b/util/src/org/aspectj/util/SoftHashMap.java @@ -0,0 +1,95 @@ +/* ******************************************************************* + * Copyright (c) 2017 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * ******************************************************************/package org.aspectj.util; + +import java.lang.ref.*; +import java.util.*; + +public class SoftHashMap<K,V> extends AbstractMap<K,V> { + private Map<K, SpecialValue> map; + private ReferenceQueue<? super V> rq = new ReferenceQueue<>(); + + public SoftHashMap() { + this.map = new HashMap<K,SpecialValue>(); + } + + class SpecialValue extends SoftReference<V> { + private final K key; + + SpecialValue(K k, V v) { + super(v, rq); + this.key = k; + } + } + + @SuppressWarnings("unchecked") + private void processQueue() { + SpecialValue sv = null; + while ((sv = (SpecialValue)rq.poll()) != null) { + map.remove(sv.key); + } + } + + @Override + public V get(Object key) { + SpecialValue ref = map.get(key); + if (ref == null) { + map.remove(key); + return null; + } + V value = ref.get(); + if (value == null) { + map.remove(ref.key); + return null; + } + return value; + } + + @Override + public V put(K k, V v) { + processQueue(); + SpecialValue sv = new SpecialValue(k, v); + SpecialValue result = map.put(k, sv); + return (result == null ? null : result.get()); + } + + @Override + public java.util.Set<Map.Entry<K,V>> entrySet() { + if (map.isEmpty()) { return Collections.<K,V>emptyMap().entrySet(); } + Map<K,V> currentContents = new HashMap<K,V>(); + for (Map.Entry<K,SpecialValue> entry: map.entrySet()) { + V currentValueForEntry = entry.getValue().get(); + if (currentValueForEntry != null) { + currentContents.put(entry.getKey(), currentValueForEntry); + } + } + return currentContents.entrySet(); + } + + @Override + public void clear() { + processQueue(); + map.clear(); + } + + @Override + public int size() { + processQueue(); + return map.size(); + } + + @Override + public V remove(Object k) { + processQueue(); + SpecialValue ref = map.remove(k); + if (ref == null) { + return null; + } + return ref.get(); + } +} |