blob: 22c9e6f51a630d0e077687c6390440eeca0aa40f [file] [log] [blame]
/**
* 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<K, V> extends LinkedHashMap<K, V> {
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}
* <p>
* 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<? extends K, ? extends V> m) {
for (Map.Entry<? extends K, ? extends V> 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<K, V> eldest) {
return size() > maxCapacity;
}
}