📄 mru.java
字号:
/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: MRU.java,v 1.8 2005/06/25 23:12:31 doomdark Exp $ */package jdbm.helper;import java.util.Enumeration;import java.util.Hashtable;import java.util.Vector;/** * MRU - Most Recently Used cache policy. * * Methods are *not* synchronized, so no concurrent access is allowed. * * @author <a href="mailto:boisvert@intalio.com">Alex Boisvert</a> * @version $Id: MRU.java,v 1.8 2005/06/25 23:12:31 doomdark Exp $ */public class MRU implements CachePolicy { /** Cached object hashtable */ Hashtable _hash = new Hashtable(); /** * Maximum number of objects in the cache. */ int _max; /** * Beginning of linked-list of cache elements. First entry is element * which has been used least recently. */ CacheEntry _first; /** * End of linked-list of cache elements. Last entry is element * which has been used most recently. */ CacheEntry _last; /** * Cache eviction listeners */ Vector listeners = new Vector(); /** * Construct an MRU with a given maximum number of objects. */ public MRU(int max) { if (max <= 0) { throw new IllegalArgumentException("MRU cache must contain at least one entry"); } _max = max; } /** * Place an object in the cache. */ public void put(Object key, Object value) throws CacheEvictionException { CacheEntry entry = (CacheEntry)_hash.get(key); if (entry != null) { entry.setValue(value); touchEntry(entry); } else { if (_hash.size() == _max) { // purge and recycle entry entry = purgeEntry(); entry.setKey(key); entry.setValue(value); } else { entry = new CacheEntry(key, value); } addEntry(entry); _hash.put(entry.getKey(), entry); } } /** * Obtain an object in the cache */ public Object get(Object key) { CacheEntry entry = (CacheEntry)_hash.get(key); if (entry != null) { touchEntry(entry); return entry.getValue(); } else { return null; } } /** * Remove an object from the cache */ public void remove(Object key) { CacheEntry entry = (CacheEntry)_hash.get(key); if (entry != null) { removeEntry(entry); _hash.remove(entry.getKey()); } } /** * Remove all objects from the cache */ public void removeAll() { _hash = new Hashtable(); _first = null; _last = null; } /** * Enumerate elements' values in the cache */ public Enumeration elements() { return new MRUEnumeration(_hash.elements()); } /** * Add a listener to this cache policy * * @param listener Listener to add to this policy */ public void addListener(CachePolicyListener listener) { if (listener == null) { throw new IllegalArgumentException("Cannot add null listener."); } if ( ! listeners.contains(listener)) { listeners.addElement(listener); } } /** * Remove a listener from this cache policy * * @param listener Listener to remove from this policy */ public void removeListener(CachePolicyListener listener) { listeners.removeElement(listener); } /** * Add a CacheEntry. Entry goes at the end of the list. */ protected void addEntry(CacheEntry entry) { if (_first == null) { _first = entry; _last = entry; } else { _last.setNext(entry); entry.setPrevious(_last); _last = entry; } } /** * Remove a CacheEntry from linked list */ protected void removeEntry(CacheEntry entry) { if (entry == _first) { _first = entry.getNext(); } if (_last == entry) { _last = entry.getPrevious(); } CacheEntry previous = entry.getPrevious(); CacheEntry next = entry.getNext(); if (previous != null) { previous.setNext(next); } if (next != null) { next.setPrevious(previous); } entry.setPrevious(null); entry.setNext(null); } /** * Place entry at the end of linked list -- Most Recently Used */ protected void touchEntry(CacheEntry entry) { if (_last == entry) { return; } removeEntry(entry); addEntry(entry); } /** * Purge least recently used object from the cache * * @return recyclable CacheEntry */ protected CacheEntry purgeEntry() throws CacheEvictionException { CacheEntry entry = _first; // Notify policy listeners first. if any of them throw an // eviction exception, then the internal data structure // remains untouched. CachePolicyListener listener; for (int i=0; i<listeners.size(); i++) { listener = (CachePolicyListener)listeners.elementAt(i); listener.cacheObjectEvicted(entry.getValue()); } removeEntry(entry); _hash.remove(entry.getKey()); entry.setValue(null); return entry; }}/** * State information for cache entries. */class CacheEntry { private Object _key; private Object _value; private CacheEntry _previous; private CacheEntry _next; CacheEntry(Object key, Object value) { _key = key; _value = value; } Object getKey() { return _key; } void setKey(Object obj) { _key = obj; } Object getValue() { return _value; } void setValue(Object obj) { _value = obj; } CacheEntry getPrevious() { return _previous; } void setPrevious(CacheEntry entry) { _previous = entry; } CacheEntry getNext() { return _next; } void setNext(CacheEntry entry) { _next = entry; }}/** * Enumeration wrapper to return actual user objects instead of * CacheEntries. */class MRUEnumeration implements Enumeration { Enumeration _enum; MRUEnumeration(Enumeration enume) { _enum = enume; } public boolean hasMoreElements() { return _enum.hasMoreElements(); } public Object nextElement() { CacheEntry entry = (CacheEntry)_enum.nextElement(); return entry.getValue(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -