/** * Copyright (c) 2011, Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.mail.utils; import java.util.LinkedHashMap; import java.util.Map; /** * A simple in-memory LRU cache, which is trivial to implement on top * of JDK's {@link LinkedHashMap}. * * LRU policy is ensured by the underlying LinkedHashMap functionality. */ public final class LruCache extends LinkedHashMap { private static final long serialVersionUID = 1L; private final int maxCapacity; /** * Creates an instance of LRUCache, with given capacity. * * @param capacity maximum number of elements in the cache. This is also * used as initialCapacity i.e. memory is allocated upfront. */ public LruCache(int capacity) { this(capacity, capacity); } /** * Creates an instance of LRUCache, with given capacity. * * @param initialCapacity initial capacity of the cache. * @param maxCapacity maximum number of elements in the cache. */ private LruCache(int initialCapacity, int maxCapacity) { super(initialCapacity, (float) 0.75, true); this.maxCapacity = maxCapacity; } // These methods are needed because the default implementation of LinkedHashMap is *not* // synchronized. /** * Gets an element from the cache, returning the element if found, or null if not * @param key * @return */ public synchronized V getElement(K key) { return get(key); } /** * Puts an element into the cache. * @param key * @param value, a non-null value. */ public synchronized void putElement(K key, V value) { put(key, value); } /** * Removes an element from the cache. Returns the removed element, or null if no such element * existed in the cache. * @param key * @return */ public synchronized V removeElement(K key) { return remove(key); } /** * {@inheritDoc} *

* Necessary to override because HashMap increases the capacity of the * hashtable before inserting the elements. However, here we call put() which * checks if we can remove the eldest element before increasing the capacity. */ @Override public synchronized void putAll(Map m) { for (Map.Entry e : m.entrySet()) { put(e.getKey(), e.getValue()); } } /** * This method is called by LinkedHashMap to check whether the eldest entry * should be removed. * * @param eldest * @return true if element should be removed. */ @Override protected synchronized boolean removeEldestEntry(Map.Entry eldest) { return size() > maxCapacity; } }