📄 lrumap.java
字号:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.commons.collections.map;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Map;
import org.apache.commons.collections.BoundedMap;
/**
* A <code>Map</code> implementation with a fixed maximum size which removes
* the least recently used entry if an entry is added when full.
* <p>
* The least recently used algorithm works on the get and put operations only.
* Iteration of any kind, including setting the value by iteration, does not
* change the order. Queries such as containsKey and containsValue or access
* via views also do not change the order.
* <p>
* The map implements <code>OrderedMap</code> and entries may be queried using
* the bidirectional <code>OrderedMapIterator</code>. The order returned is
* least recently used to most recently used. Iterators from map views can
* also be cast to <code>OrderedIterator</code> if required.
* <p>
* All the available iterators can be reset back to the start by casting to
* <code>ResettableIterator</code> and calling <code>reset()</code>.
* <p>
* <strong>Note that LRUMap is not synchronized and is not thread-safe.</strong>
* If you wish to use this map from multiple threads concurrently, you must use
* appropriate synchronization. The simplest approach is to wrap this map
* using {@link java.util.Collections#synchronizedMap(Map)}. This class may throw
* <code>NullPointerException</code>'s when accessed by concurrent threads.
*
* @since Commons Collections 3.0 (previously in main package v1.0)
* @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
*
* @author James Strachan
* @author Morgan Delagrange
* @author Stephen Colebourne
* @author Mike Pettypiece
* @author Mario Ivankovits
*/
public class LRUMap
extends AbstractLinkedMap implements BoundedMap, Serializable, Cloneable {
/** Serialisation version */
private static final long serialVersionUID = -612114643488955218L;
/** Default maximum size */
protected static final int DEFAULT_MAX_SIZE = 100;
/** Maximum size */
private transient int maxSize;
/** Scan behaviour */
private boolean scanUntilRemovable;
/**
* Constructs a new empty map with a maximum size of 100.
*/
public LRUMap() {
this(DEFAULT_MAX_SIZE, DEFAULT_LOAD_FACTOR, false);
}
/**
* Constructs a new, empty map with the specified maximum size.
*
* @param maxSize the maximum size of the map
* @throws IllegalArgumentException if the maximum size is less than one
*/
public LRUMap(int maxSize) {
this(maxSize, DEFAULT_LOAD_FACTOR);
}
/**
* Constructs a new, empty map with the specified maximum size.
*
* @param maxSize the maximum size of the map
* @param scanUntilRemovable scan until a removeable entry is found, default false
* @throws IllegalArgumentException if the maximum size is less than one
* @since Commons Collections 3.1
*/
public LRUMap(int maxSize, boolean scanUntilRemovable) {
this(maxSize, DEFAULT_LOAD_FACTOR, scanUntilRemovable);
}
/**
* Constructs a new, empty map with the specified initial capacity and
* load factor.
*
* @param maxSize the maximum size of the map, -1 for no limit,
* @param loadFactor the load factor
* @throws IllegalArgumentException if the maximum size is less than one
* @throws IllegalArgumentException if the load factor is less than zero
*/
public LRUMap(int maxSize, float loadFactor) {
this(maxSize, loadFactor, false);
}
/**
* Constructs a new, empty map with the specified initial capacity and
* load factor.
*
* @param maxSize the maximum size of the map, -1 for no limit,
* @param loadFactor the load factor
* @param scanUntilRemovable scan until a removeable entry is found, default false
* @throws IllegalArgumentException if the maximum size is less than one
* @throws IllegalArgumentException if the load factor is less than zero
* @since Commons Collections 3.1
*/
public LRUMap(int maxSize, float loadFactor, boolean scanUntilRemovable) {
super((maxSize < 1 ? DEFAULT_CAPACITY : maxSize), loadFactor);
if (maxSize < 1) {
throw new IllegalArgumentException("LRUMap max size must be greater than 0");
}
this.maxSize = maxSize;
this.scanUntilRemovable = scanUntilRemovable;
}
/**
* Constructor copying elements from another map.
* <p>
* The maximum size is set from the map's size.
*
* @param map the map to copy
* @throws NullPointerException if the map is null
* @throws IllegalArgumentException if the map is empty
*/
public LRUMap(Map map) {
this(map, false);
}
/**
* Constructor copying elements from another map.
* <p/>
* The maximum size is set from the map's size.
*
* @param map the map to copy
* @param scanUntilRemovable scan until a removeable entry is found, default false
* @throws NullPointerException if the map is null
* @throws IllegalArgumentException if the map is empty
* @since Commons Collections 3.1
*/
public LRUMap(Map map, boolean scanUntilRemovable) {
this(map.size(), DEFAULT_LOAD_FACTOR, scanUntilRemovable);
putAll(map);
}
//-----------------------------------------------------------------------
/**
* Gets the value mapped to the key specified.
* <p>
* This operation changes the position of the key in the map to the
* most recently used position (first).
*
* @param key the key
* @return the mapped value, null if no match
*/
public Object get(Object key) {
LinkEntry entry = (LinkEntry) getEntry(key);
if (entry == null) {
return null;
}
moveToMRU(entry);
return entry.getValue();
}
//-----------------------------------------------------------------------
/**
* Moves an entry to the MRU position at the end of the list.
* <p>
* This implementation moves the updated entry to the end of the list.
*
* @param entry the entry to update
*/
protected void moveToMRU(LinkEntry entry) {
if (entry.after != header) {
modCount++;
// remove
entry.before.after = entry.after;
entry.after.before = entry.before;
// add first
entry.after = header;
entry.before = header.before;
header.before.after = entry;
header.before = entry;
} else if (entry == header) {
throw new IllegalStateException("Can't move header to MRU" +
" (please report this to commons-dev@jakarta.apache.org)");
}
}
/**
* Updates an existing key-value mapping.
* <p>
* This implementation moves the updated entry to the top of the list
* using {@link #moveToMRU(AbstractLinkedMap.LinkEntry)}.
*
* @param entry the entry to update
* @param newValue the new value to store
*/
protected void updateEntry(HashEntry entry, Object newValue) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -