001: /*
002: * *****************************************************************************
003: * Copyright (C) 2006, International Business Machines Corporation and others.
004: * All Rights Reserved.
005: * *****************************************************************************
006: */
007: package com.ibm.icu.impl;
008:
009: import java.util.HashMap;
010: import java.util.Iterator;
011: import java.util.LinkedList;
012: import java.util.Map;
013: import java.util.Set;
014:
015: /**
016: * JDK1.4 LinkedHashMap equivalent implementation for
017: * Java foundation profile support. This class is used
018: * by <code>com.ibm.icu.impl.LRUMap</code> on eclipse
019: * distributions, which require JDK1.3/Java Foundation
020: * profile support.
021: */
022: public class LinkedHashMap extends HashMap {
023: private static final long serialVersionUID = -2497823480436618075L;
024:
025: private boolean accessOrder = false;
026: private LinkedList keyList = new LinkedList();
027:
028: public LinkedHashMap() {
029: super ();
030: }
031:
032: public LinkedHashMap(int initialCapacity) {
033: super (initialCapacity);
034: }
035:
036: public LinkedHashMap(int initialCapacity, float loadFactor) {
037: super (initialCapacity, loadFactor);
038: }
039:
040: public LinkedHashMap(int initialCapacity, float loadFactor,
041: boolean accessOrder) {
042: super (initialCapacity, loadFactor);
043: this .accessOrder = accessOrder;
044: }
045:
046: public LinkedHashMap(Map m) {
047: super ();
048: putAll(m);
049: }
050:
051: public void clear() {
052: super .clear();
053: keyList.clear();
054: }
055:
056: public Object remove(Object key) {
057: Object value = super .remove(key);
058: if (value == null) {
059: // null might be returned for a map entry
060: // for null value. So we need to check if
061: // the key is actually available or not.
062: // If the key list contains the key, then
063: // remove the key from the list.
064: int index = getKeyIndex(key);
065: if (index >= 0) {
066: keyList.remove(index);
067: }
068: }
069: return value;
070: }
071:
072: public Object get(Object key) {
073: Object value = super .get(key);
074: if (accessOrder) {
075: // When accessOrder is true, move the key
076: // to the end of the list
077: int index = getKeyIndex(key);
078: if (index >= 0) {
079: if (index != keyList.size() - 1) {
080: keyList.remove(index);
081: keyList.addLast(key);
082: }
083: }
084: }
085: return value;
086: }
087:
088: public void putAll(Map m) {
089: Set keySet = m.keySet();
090: Iterator it = keySet.iterator();
091: while (it.hasNext()) {
092: Object key = it.next();
093: Object value = m.get(key);
094: put(key, value);
095: }
096: }
097:
098: public Object put(Object key, Object value) {
099: Object oldValue = super .put(key, value);
100:
101: // Move the key to the end of key list
102: // if it exists. If not, append the key
103: // to the end of key list
104: int index = getKeyIndex(key);
105: if (index >= 0) {
106: if (index != keyList.size() - 1) {
107: keyList.remove(index);
108: keyList.addLast(key);
109: }
110: } else {
111: keyList.addLast(key);
112: }
113:
114: // Check if we need to remove the eldest
115: // entry.
116: Object eldestKey = keyList.getFirst();
117: Object eldestValue = super .get(eldestKey);
118: MapEntry entry = new MapEntry(eldestKey, eldestValue);
119: if (removeEldestEntry(entry)) {
120: keyList.removeFirst();
121: super .remove(eldestKey);
122: }
123:
124: return oldValue;
125: }
126:
127: protected boolean removeEldestEntry(Map.Entry eldest) {
128: return false;
129: }
130:
131: private int getKeyIndex(Object key) {
132: int index = -1;
133: for (int i = 0; i < keyList.size(); i++) {
134: Object o = keyList.get(i);
135: if (o.equals(key)) {
136: index = i;
137: break;
138: }
139: }
140: return index;
141: }
142:
143: protected static class MapEntry implements Map.Entry {
144: private Object key;
145: private Object value;
146:
147: private MapEntry(Object key, Object value) {
148: this .key = key;
149: this .value = value;
150: }
151:
152: public boolean equals(Object o) {
153: Object otherKey = ((Map.Entry) o).getKey();
154: Object otherValue = ((Map.Entry) o).getValue();
155: if (key.equals(otherKey) && value.equals(otherValue)) {
156: return true;
157: }
158: return false;
159: }
160:
161: public Object getKey() {
162: return key;
163: }
164:
165: public Object getValue() {
166: return value;
167: }
168:
169: public Object setValue(Object value) {
170: Object oldValue = this.value;
171: this.value = value;
172: return oldValue;
173: }
174: }
175: }
|