/******************************************************************************* * Copyright © 2011, 2013 IBM Corporation and others. * 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 * * Contributors: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.compiler.internal.core.utils; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; /** * @author winghong */ public class SoftLRUCache { private static final boolean DEBUG = false; private static class SoftReferenceWithKey extends SoftReference { Object key; SoftReferenceWithKey(Object key, Object referent, ReferenceQueue q) { super(referent, q); this.key = key; } } private Map softReferences; private ReferenceQueue referenceQueue; public SoftLRUCache() { this.softReferences = new LinkedHashMap(16, 0.75f, true); this.referenceQueue = new ReferenceQueue(); } public SoftLRUCache(final int maxSize) { this.softReferences = new LinkedHashMap((int)(maxSize * 0.75f), 0.75f, true) { private static final long serialVersionUID = 1503311551124552810L; protected boolean removeEldestEntry(Entry eldest) { return size() > maxSize; } }; this.referenceQueue = new ReferenceQueue(); } public void put(Object key, Object value) { if(DEBUG) System.out.println("Put: " + key); //$NON-NLS-1$ removeClearedReferences(); softReferences.put(key, new SoftReferenceWithKey(key, value, referenceQueue)); } public Object get(Object key) { removeClearedReferences(); SoftReferenceWithKey ref = (SoftReferenceWithKey) softReferences.get(key); if(ref == null) { return null; } Object result = ref.get(); if(DEBUG && result == null) System.out.println("Key " + key + " has been cleared"); //$NON-NLS-1$ //$NON-NLS-2$ return result; } public void remove(Object key) { removeClearedReferences(); softReferences.remove(key); } private void removeClearedReferences() { SoftReferenceWithKey ref; while((ref = (SoftReferenceWithKey) referenceQueue.poll()) != null) { if(DEBUG) System.out.println("Removing cleared soft reference"); //$NON-NLS-1$ softReferences.remove(ref.key); } } public static void main(String[] args) { SoftLRUCache cache = new SoftLRUCache(5); for(int i = 0; i < 1000; i++) { Integer key = new Integer((int) Math.floor(Math.random() * 100)); if(Math.round(Math.random()) == 0) { int sizeInKilobytes = (int) Math.floor(Math.random() * 100); int[] value = new int[sizeInKilobytes * 1024]; cache.put(key, value); } else { if(cache.get(key) != null) { System.out.println("Get: " + key); //$NON-NLS-1$ } else { System.out.println("Key Not found: " + key); //$NON-NLS-1$ } } } } }