From b7e4aff1c15a0984d4ca772ffb82cdd9b0f6fa57 Mon Sep 17 00:00:00 2001 From: Andy Clement Date: Thu, 28 Sep 2017 15:52:29 -0700 Subject: Reusable SoftHashMap utility class --- util/src/org/aspectj/util/SoftHashMap.java | 95 ++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 util/src/org/aspectj/util/SoftHashMap.java (limited to 'util') 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 extends AbstractMap { + private Map map; + private ReferenceQueue rq = new ReferenceQueue<>(); + + public SoftHashMap() { + this.map = new HashMap(); + } + + class SpecialValue extends SoftReference { + 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> entrySet() { + if (map.isEmpty()) { return Collections.emptyMap().entrySet(); } + Map currentContents = new HashMap(); + for (Map.Entry 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(); + } +} -- cgit v1.2.3