Change order of LRUMap to LRU to MRU
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@131424 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7feafdc4de
commit
2ec031411c
Binary file not shown.
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/map/LRUMap.java,v 1.2 2003/12/07 23:59:13 scolebourne Exp $
|
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/map/LRUMap.java,v 1.3 2003/12/11 00:46:12 scolebourne Exp $
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*
|
*
|
||||||
* The Apache Software License, Version 1.1
|
* The Apache Software License, Version 1.1
|
||||||
|
@ -74,18 +74,14 @@ import java.util.Map;
|
||||||
* <p>
|
* <p>
|
||||||
* The map implements <code>OrderedMap</code> and entries may be queried using
|
* The map implements <code>OrderedMap</code> and entries may be queried using
|
||||||
* the bidirectional <code>OrderedMapIterator</code>. The order returned is
|
* the bidirectional <code>OrderedMapIterator</code>. The order returned is
|
||||||
* most recently used to least recently used. Iterators from map views can
|
* least recently used to most recently used. Iterators from map views can
|
||||||
* also be cast to <code>OrderedIterator</code> if required.
|
* also be cast to <code>OrderedIterator</code> if required.
|
||||||
* <p>
|
* <p>
|
||||||
* All the available iterators can be reset back to the start by casting to
|
* All the available iterators can be reset back to the start by casting to
|
||||||
* <code>ResettableIterator</code> and calling <code>reset()</code>.
|
* <code>ResettableIterator</code> and calling <code>reset()</code>.
|
||||||
* <p>
|
|
||||||
* NOTE: The order of the map has changed from the previous version located
|
|
||||||
* in the main collections package. The map is now ordered most recently used
|
|
||||||
* to least recently used.
|
|
||||||
*
|
*
|
||||||
* @since Commons Collections 3.0
|
* @since Commons Collections 3.0
|
||||||
* @version $Revision: 1.2 $ $Date: 2003/12/07 23:59:13 $
|
* @version $Revision: 1.3 $ $Date: 2003/12/11 00:46:12 $
|
||||||
*
|
*
|
||||||
* @author James Strachan
|
* @author James Strachan
|
||||||
* @author Morgan Delagrange
|
* @author Morgan Delagrange
|
||||||
|
@ -164,30 +160,30 @@ public class LRUMap extends AbstractLinkedMap implements Serializable, Cloneable
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
moveFirst(entry);
|
moveToMRU(entry);
|
||||||
return entry.getValue();
|
return entry.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* Updates an existing key-value mapping.
|
* Moves an entry to the MRU position at the end of the list.
|
||||||
* This implementation moves the updated entry to the top of the list.
|
* This implementation moves the updated entry to the end of the list.
|
||||||
*
|
*
|
||||||
* @param entry the entry to update
|
* @param entry the entry to update
|
||||||
* @param newValue the new value to store
|
* @param newValue the new value to store
|
||||||
* @return value the previous value
|
* @return value the previous value
|
||||||
*/
|
*/
|
||||||
protected void moveFirst(LinkEntry entry) {
|
protected void moveToMRU(LinkEntry entry) {
|
||||||
if (entry.before != header) {
|
if (entry.after != header) {
|
||||||
modCount++;
|
modCount++;
|
||||||
// remove
|
// remove
|
||||||
entry.after.before = entry.before;
|
|
||||||
entry.before.after = entry.after;
|
entry.before.after = entry.after;
|
||||||
|
entry.after.before = entry.before;
|
||||||
// add first
|
// add first
|
||||||
entry.before = header;
|
entry.after = header;
|
||||||
entry.after = header.after;
|
entry.before = header.before;
|
||||||
header.after.before = entry;
|
header.before.after = entry;
|
||||||
header.after = entry;
|
header.before = entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +196,7 @@ public class LRUMap extends AbstractLinkedMap implements Serializable, Cloneable
|
||||||
* @return value the previous value
|
* @return value the previous value
|
||||||
*/
|
*/
|
||||||
protected void updateEntry(HashEntry entry, Object newValue) {
|
protected void updateEntry(HashEntry entry, Object newValue) {
|
||||||
moveFirst((LinkEntry) entry); // handles modCount
|
moveToMRU((LinkEntry) entry); // handles modCount
|
||||||
entry.setValue(newValue);
|
entry.setValue(newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,41 +213,39 @@ public class LRUMap extends AbstractLinkedMap implements Serializable, Cloneable
|
||||||
*/
|
*/
|
||||||
protected void addMapping(int hashIndex, int hashCode, Object key, Object value) {
|
protected void addMapping(int hashIndex, int hashCode, Object key, Object value) {
|
||||||
if (size >= maxSize && removeLRU(header.before)) {
|
if (size >= maxSize && removeLRU(header.before)) {
|
||||||
LinkEntry entry = header.before;
|
reuseMapping(header.after, hashIndex, hashCode, key, value);
|
||||||
// remove from current location
|
|
||||||
int removeIndex = hashIndex(entry.hashCode, data.length);
|
|
||||||
HashEntry loop = data[removeIndex];
|
|
||||||
HashEntry previous = null;
|
|
||||||
while (loop != entry) {
|
|
||||||
previous = loop;
|
|
||||||
loop = loop.next;
|
|
||||||
}
|
|
||||||
modCount++;
|
|
||||||
removeEntry(entry, removeIndex, previous);
|
|
||||||
reuseEntry(entry, hashIndex, hashCode, key, value);
|
|
||||||
addEntry(entry, hashIndex);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
super.addMapping(hashIndex, hashCode, key, value);
|
super.addMapping(hashIndex, hashCode, key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new entry into this map using access order.
|
* Reuses an entry by removing it and moving it to a new place in the map.
|
||||||
* <p>
|
|
||||||
* This implementation adds the entry to the data storage table and
|
|
||||||
* to the start of the linked list.
|
|
||||||
*
|
*
|
||||||
* @param entry the entry to add
|
* @param entry the entry to reuse
|
||||||
* @param hashIndex the index into the data array to store at
|
* @param hashIndex the index into the data array to store at
|
||||||
|
* @param hashCode the hash code of the key to add
|
||||||
|
* @param key the key to add
|
||||||
|
* @param value the value to add
|
||||||
|
* @return the value previously mapped to this key, null if none
|
||||||
*/
|
*/
|
||||||
protected void addEntry(HashEntry entry, int hashIndex) {
|
protected void reuseMapping(LinkEntry entry, int hashIndex, int hashCode, Object key, Object value) {
|
||||||
LinkEntry link = (LinkEntry) entry;
|
// find the entry before the entry specified in the hash table
|
||||||
link.before = header;
|
// remember that the parameters (except the first) refer to the new entry,
|
||||||
link.after = header.after;
|
// not the old one
|
||||||
header.after.before = link;
|
int removeIndex = hashIndex(entry.hashCode, data.length);
|
||||||
header.after = link;
|
HashEntry loop = data[removeIndex];
|
||||||
data[hashIndex] = entry;
|
HashEntry previous = null;
|
||||||
|
while (loop != entry) {
|
||||||
|
previous = loop;
|
||||||
|
loop = loop.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reuse the entry
|
||||||
|
modCount++;
|
||||||
|
removeEntry(entry, removeIndex, previous);
|
||||||
|
reuseEntry(entry, hashIndex, hashCode, key, value);
|
||||||
|
addEntry(entry, hashIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/map/TestLRUMap.java,v 1.2 2003/12/07 23:59:12 scolebourne Exp $
|
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/map/TestLRUMap.java,v 1.3 2003/12/11 00:46:12 scolebourne Exp $
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*
|
*
|
||||||
* The Apache Software License, Version 1.1
|
* The Apache Software License, Version 1.1
|
||||||
|
@ -58,11 +58,9 @@
|
||||||
package org.apache.commons.collections.map;
|
package org.apache.commons.collections.map;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.textui.TestRunner;
|
import junit.textui.TestRunner;
|
||||||
|
@ -74,7 +72,7 @@ import org.apache.commons.collections.ResettableIterator;
|
||||||
/**
|
/**
|
||||||
* JUnit tests.
|
* JUnit tests.
|
||||||
*
|
*
|
||||||
* @version $Revision: 1.2 $ $Date: 2003/12/07 23:59:12 $
|
* @version $Revision: 1.3 $ $Date: 2003/12/11 00:46:12 $
|
||||||
*
|
*
|
||||||
* @author Stephen Colebourne
|
* @author Stephen Colebourne
|
||||||
*/
|
*/
|
||||||
|
@ -126,44 +124,44 @@ public class TestLRUMap extends AbstractTestOrderedMap {
|
||||||
assertEquals(true, map.isFull());
|
assertEquals(true, map.isFull());
|
||||||
assertEquals(2, map.maxSize());
|
assertEquals(2, map.maxSize());
|
||||||
it = map.keySet().iterator();
|
it = map.keySet().iterator();
|
||||||
assertSame(keys[1], it.next());
|
|
||||||
assertSame(keys[0], it.next());
|
assertSame(keys[0], it.next());
|
||||||
|
assertSame(keys[1], it.next());
|
||||||
it = map.values().iterator();
|
it = map.values().iterator();
|
||||||
assertSame(values[1], it.next());
|
|
||||||
assertSame(values[0], it.next());
|
assertSame(values[0], it.next());
|
||||||
|
assertSame(values[1], it.next());
|
||||||
|
|
||||||
map.put(keys[2], values[2]);
|
map.put(keys[2], values[2]);
|
||||||
assertEquals(2, map.size());
|
assertEquals(2, map.size());
|
||||||
assertEquals(true, map.isFull());
|
assertEquals(true, map.isFull());
|
||||||
assertEquals(2, map.maxSize());
|
assertEquals(2, map.maxSize());
|
||||||
it = map.keySet().iterator();
|
it = map.keySet().iterator();
|
||||||
assertSame(keys[2], it.next());
|
|
||||||
assertSame(keys[1], it.next());
|
assertSame(keys[1], it.next());
|
||||||
|
assertSame(keys[2], it.next());
|
||||||
it = map.values().iterator();
|
it = map.values().iterator();
|
||||||
assertSame(values[2], it.next());
|
|
||||||
assertSame(values[1], it.next());
|
assertSame(values[1], it.next());
|
||||||
|
assertSame(values[2], it.next());
|
||||||
|
|
||||||
map.put(keys[2], values[0]);
|
map.put(keys[2], values[0]);
|
||||||
assertEquals(2, map.size());
|
assertEquals(2, map.size());
|
||||||
assertEquals(true, map.isFull());
|
assertEquals(true, map.isFull());
|
||||||
assertEquals(2, map.maxSize());
|
assertEquals(2, map.maxSize());
|
||||||
it = map.keySet().iterator();
|
it = map.keySet().iterator();
|
||||||
assertSame(keys[2], it.next());
|
|
||||||
assertSame(keys[1], it.next());
|
assertSame(keys[1], it.next());
|
||||||
|
assertSame(keys[2], it.next());
|
||||||
it = map.values().iterator();
|
it = map.values().iterator();
|
||||||
assertSame(values[0], it.next());
|
|
||||||
assertSame(values[1], it.next());
|
assertSame(values[1], it.next());
|
||||||
|
assertSame(values[0], it.next());
|
||||||
|
|
||||||
map.put(keys[1], values[3]);
|
map.put(keys[1], values[3]);
|
||||||
assertEquals(2, map.size());
|
assertEquals(2, map.size());
|
||||||
assertEquals(true, map.isFull());
|
assertEquals(true, map.isFull());
|
||||||
assertEquals(2, map.maxSize());
|
assertEquals(2, map.maxSize());
|
||||||
it = map.keySet().iterator();
|
it = map.keySet().iterator();
|
||||||
assertSame(keys[1], it.next());
|
|
||||||
assertSame(keys[2], it.next());
|
assertSame(keys[2], it.next());
|
||||||
|
assertSame(keys[1], it.next());
|
||||||
it = map.values().iterator();
|
it = map.values().iterator();
|
||||||
assertSame(values[3], it.next());
|
|
||||||
assertSame(values[0], it.next());
|
assertSame(values[0], it.next());
|
||||||
|
assertSame(values[3], it.next());
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
@ -190,8 +188,8 @@ public class TestLRUMap extends AbstractTestOrderedMap {
|
||||||
Iterator it = null;
|
Iterator it = null;
|
||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
map.put(keys[1], values[1]);
|
|
||||||
map.put(keys[0], values[0]);
|
map.put(keys[0], values[0]);
|
||||||
|
map.put(keys[1], values[1]);
|
||||||
it = map.keySet().iterator();
|
it = map.keySet().iterator();
|
||||||
assertSame(keys[0], it.next());
|
assertSame(keys[0], it.next());
|
||||||
assertSame(keys[1], it.next());
|
assertSame(keys[1], it.next());
|
||||||
|
@ -199,142 +197,59 @@ public class TestLRUMap extends AbstractTestOrderedMap {
|
||||||
assertSame(values[0], it.next());
|
assertSame(values[0], it.next());
|
||||||
assertSame(values[1], it.next());
|
assertSame(values[1], it.next());
|
||||||
|
|
||||||
// change to order
|
// no change to order
|
||||||
map.put(keys[1], values[1]);
|
map.put(keys[1], values[1]);
|
||||||
it = map.keySet().iterator();
|
it = map.keySet().iterator();
|
||||||
assertSame(keys[1], it.next());
|
|
||||||
assertSame(keys[0], it.next());
|
assertSame(keys[0], it.next());
|
||||||
|
assertSame(keys[1], it.next());
|
||||||
it = map.values().iterator();
|
it = map.values().iterator();
|
||||||
assertSame(values[1], it.next());
|
|
||||||
assertSame(values[0], it.next());
|
assertSame(values[0], it.next());
|
||||||
|
assertSame(values[1], it.next());
|
||||||
|
|
||||||
// no change to order
|
// no change to order
|
||||||
map.put(keys[1], values[2]);
|
map.put(keys[1], values[2]);
|
||||||
it = map.keySet().iterator();
|
it = map.keySet().iterator();
|
||||||
assertSame(keys[1], it.next());
|
|
||||||
assertSame(keys[0], it.next());
|
assertSame(keys[0], it.next());
|
||||||
|
assertSame(keys[1], it.next());
|
||||||
it = map.values().iterator();
|
it = map.values().iterator();
|
||||||
assertSame(values[2], it.next());
|
|
||||||
assertSame(values[0], it.next());
|
assertSame(values[0], it.next());
|
||||||
|
assertSame(values[2], it.next());
|
||||||
|
|
||||||
// change to order
|
// change to order
|
||||||
map.put(keys[0], values[3]);
|
map.put(keys[0], values[3]);
|
||||||
it = map.keySet().iterator();
|
it = map.keySet().iterator();
|
||||||
assertSame(keys[0], it.next());
|
|
||||||
assertSame(keys[1], it.next());
|
assertSame(keys[1], it.next());
|
||||||
|
assertSame(keys[0], it.next());
|
||||||
it = map.values().iterator();
|
it = map.values().iterator();
|
||||||
assertSame(values[3], it.next());
|
|
||||||
assertSame(values[2], it.next());
|
assertSame(values[2], it.next());
|
||||||
|
assertSame(values[3], it.next());
|
||||||
|
|
||||||
// change to order
|
// change to order
|
||||||
map.get(keys[1]);
|
map.get(keys[1]);
|
||||||
it = map.keySet().iterator();
|
it = map.keySet().iterator();
|
||||||
assertSame(keys[1], it.next());
|
|
||||||
assertSame(keys[0], it.next());
|
assertSame(keys[0], it.next());
|
||||||
|
assertSame(keys[1], it.next());
|
||||||
it = map.values().iterator();
|
it = map.values().iterator();
|
||||||
assertSame(values[2], it.next());
|
|
||||||
assertSame(values[3], it.next());
|
assertSame(values[3], it.next());
|
||||||
|
assertSame(values[2], it.next());
|
||||||
|
|
||||||
// change to order
|
// change to order
|
||||||
map.get(keys[0]);
|
map.get(keys[0]);
|
||||||
it = map.keySet().iterator();
|
it = map.keySet().iterator();
|
||||||
assertSame(keys[0], it.next());
|
|
||||||
assertSame(keys[1], it.next());
|
assertSame(keys[1], it.next());
|
||||||
|
assertSame(keys[0], it.next());
|
||||||
it = map.values().iterator();
|
it = map.values().iterator();
|
||||||
assertSame(values[3], it.next());
|
|
||||||
assertSame(values[2], it.next());
|
assertSame(values[2], it.next());
|
||||||
|
assertSame(values[3], it.next());
|
||||||
|
|
||||||
// no change to order
|
// no change to order
|
||||||
map.get(keys[0]);
|
map.get(keys[0]);
|
||||||
it = map.keySet().iterator();
|
it = map.keySet().iterator();
|
||||||
assertSame(keys[0], it.next());
|
|
||||||
assertSame(keys[1], it.next());
|
assertSame(keys[1], it.next());
|
||||||
|
assertSame(keys[0], it.next());
|
||||||
it = map.values().iterator();
|
it = map.values().iterator();
|
||||||
assertSame(values[3], it.next());
|
|
||||||
assertSame(values[2], it.next());
|
assertSame(values[2], it.next());
|
||||||
}
|
assertSame(values[3], it.next());
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
|
||||||
public void testFirstKey() { // override
|
|
||||||
resetEmpty();
|
|
||||||
OrderedMap ordered = (OrderedMap) map;
|
|
||||||
try {
|
|
||||||
ordered.firstKey();
|
|
||||||
fail();
|
|
||||||
} catch (NoSuchElementException ex) {}
|
|
||||||
|
|
||||||
resetFull();
|
|
||||||
ordered = (OrderedMap) map;
|
|
||||||
Object confirmedFirst = confirmed.keySet().iterator().next();
|
|
||||||
ordered.get(confirmedFirst);
|
|
||||||
assertEquals(confirmedFirst, ordered.firstKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testLastKey() { // override
|
|
||||||
resetEmpty();
|
|
||||||
OrderedMap ordered = (OrderedMap) map;
|
|
||||||
try {
|
|
||||||
ordered.lastKey();
|
|
||||||
fail();
|
|
||||||
} catch (NoSuchElementException ex) {}
|
|
||||||
|
|
||||||
resetFull();
|
|
||||||
ordered = (OrderedMap) map;
|
|
||||||
Object confirmedFirst = confirmed.keySet().iterator().next();
|
|
||||||
// access order, thus first in is now in last place
|
|
||||||
assertEquals(confirmedFirst, ordered.lastKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
|
||||||
public void testNextKey() { // override
|
|
||||||
resetEmpty();
|
|
||||||
OrderedMap ordered = (OrderedMap) map;
|
|
||||||
assertEquals(null, ordered.nextKey(getOtherKeys()[0]));
|
|
||||||
if (isAllowNullKey() == false) {
|
|
||||||
try {
|
|
||||||
assertEquals(null, ordered.nextKey(null)); // this is allowed too
|
|
||||||
} catch (NullPointerException ex) {}
|
|
||||||
} else {
|
|
||||||
assertEquals(null, ordered.nextKey(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
resetFull();
|
|
||||||
ordered = (OrderedMap) map;
|
|
||||||
List list = new ArrayList(confirmed.keySet());
|
|
||||||
Collections.reverse(list); // first into map is eldest
|
|
||||||
Iterator it = list.iterator();
|
|
||||||
Object confirmedLast = it.next();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
Object confirmedObject = it.next();
|
|
||||||
assertEquals(confirmedObject, ordered.nextKey(confirmedLast));
|
|
||||||
confirmedLast = confirmedObject;
|
|
||||||
}
|
|
||||||
assertEquals(null, ordered.nextKey(confirmedLast));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testPreviousKey() { // override
|
|
||||||
resetEmpty();
|
|
||||||
OrderedMap ordered = (OrderedMap) map;
|
|
||||||
assertEquals(null, ordered.previousKey(getOtherKeys()[0]));
|
|
||||||
if (isAllowNullKey() == false) {
|
|
||||||
try {
|
|
||||||
assertEquals(null, ordered.previousKey(null)); // this is allowed too
|
|
||||||
} catch (NullPointerException ex) {}
|
|
||||||
} else {
|
|
||||||
assertEquals(null, ordered.previousKey(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
resetFull();
|
|
||||||
ordered = (OrderedMap) map;
|
|
||||||
List list = new ArrayList(confirmed.keySet());
|
|
||||||
Iterator it = list.iterator();
|
|
||||||
Object confirmedLast = it.next();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
Object confirmedObject = it.next();
|
|
||||||
assertEquals(confirmedObject, ordered.previousKey(confirmedLast));
|
|
||||||
confirmedLast = confirmedObject;
|
|
||||||
}
|
|
||||||
assertEquals(null, ordered.previousKey(confirmedLast));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// public void testCreate() throws Exception {
|
// public void testCreate() throws Exception {
|
||||||
|
|
Loading…
Reference in New Issue