Methods Summary |
---|
public void | clear()Implements {@link Map#clear()}.
modCount++;
// remove all from the underlying map
entries.clear();
// and the list
sentinel.next = sentinel;
sentinel.prev = sentinel;
|
public java.lang.Object | clone()Creates a shallow copy of this object, preserving the internal structure
by copying only references. The keys and values themselves are not
clone() 'd. The cloned object maintains the same sequence.
// yes, calling super.clone() silly since we're just blowing away all
// the stuff that super might be doing anyway, but for motivations on
// this, see:
// http://www.javaworld.com/javaworld/jw-01-1999/jw-01-object.html
SequencedHashMap map = (SequencedHashMap) super.clone();
// create new, empty sentinel
map.sentinel = createSentinel();
// create a new, empty entry map
// note: this does not preserve the initial capacity and load factor.
map.entries = new HashMap();
// add all the mappings
map.putAll(this);
// Note: We cannot just clone the hashmap and sentinel because we must
// duplicate our internal structures. Cloning those two will not clone all
// the other entries they reference, and so the cloned hash map will not be
// able to maintain internal consistency because there are two objects with
// the same entries. See discussion in the Entry implementation on why we
// cannot implement a clone of the Entry (and thus why we need to recreate
// everything).
return map;
|
public boolean | containsKey(java.lang.Object key)Implements {@link Map#containsKey(Object)}.
// pass on to underlying map implementation
return entries.containsKey(key);
|
public boolean | containsValue(java.lang.Object value)Implements {@link Map#containsValue(Object)}.
// unfortunately, we cannot just pass this call to the underlying map
// because we are mapping keys to entries, not keys to values. The
// underlying map doesn't have an efficient implementation anyway, so this
// isn't a big deal.
// do null comparison outside loop so we only need to do it once. This
// provides a tighter, more efficient loop at the expense of slight
// code duplication.
if (value == null) {
for (Entry pos = sentinel.next; pos != sentinel; pos = pos.next) {
if (pos.getValue() == null)
return true;
}
} else {
for (Entry pos = sentinel.next; pos != sentinel; pos = pos.next) {
if (value.equals(pos.getValue()))
return true;
}
}
return false;
|
private static final org.apache.axis.collections.SequencedHashMap$Entry | createSentinel()Construct an empty sentinel used to hold the head (sentinel.next) and the
tail (sentinel.prev) of the list. The sentinal has a null
key and value.
Entry s = new Entry(null, null);
s.prev = s;
s.next = s;
return s;
|
public java.util.Set | entrySet()Implements {@link Map#entrySet()}.
return new AbstractSet() {
// helper
private Entry findEntry(Object o) {
if (o == null)
return null;
if (!(o instanceof Map.Entry))
return null;
Map.Entry e = (Map.Entry) o;
Entry entry = (Entry) entries.get(e.getKey());
if (entry != null && entry.equals(e))
return entry;
else
return null;
}
// required impl
public Iterator iterator() {
return new OrderedIterator(ENTRY);
}
public boolean remove(Object o) {
Entry e = findEntry(o);
if (e == null)
return false;
return SequencedHashMap.this.removeImpl(e.getKey()) != null;
}
// more efficient impls than abstract collection
public void clear() {
SequencedHashMap.this.clear();
}
public int size() {
return SequencedHashMap.this.size();
}
public boolean isEmpty() {
return SequencedHashMap.this.isEmpty();
}
public boolean contains(Object o) {
return findEntry(o) != null;
}
};
|
public boolean | equals(java.lang.Object obj)Implements {@link Map#equals(Object)}.
if (obj == null)
return false;
if (obj == this)
return true;
if (!(obj instanceof Map))
return false;
return entrySet().equals(((Map) obj).entrySet());
|
public java.lang.Object | get(java.lang.Object o)Implements {@link Map#get(Object)}.
// find entry for the specified key object
Entry entry = (Entry) entries.get(o);
if (entry == null)
return null;
return entry.getValue();
|
public java.lang.Object | get(int index)Gets the key at the specified index.
return getEntry(index).getKey();
|
private java.util.Map$Entry | getEntry(int index)Returns the Map.Entry at the specified index
Entry pos = sentinel;
if (index < 0) {
throw new ArrayIndexOutOfBoundsException(Messages.getMessage("seqHashMapArrayIndexOutOfBoundsException01", new Integer(index).toString()));
}
// loop to one before the position
int i = -1;
while (i < (index - 1) && pos.next != sentinel) {
i++;
pos = pos.next;
}
// pos.next is the requested position
// if sentinel is next, past end of list
if (pos.next == sentinel) {
throw new ArrayIndexOutOfBoundsException(Messages.getMessage("seqHashMapArrayIndexOutOfBoundsException02",
new Integer(index).toString(),
new Integer(i + 1).toString()));
}
return pos.next;
|
public java.util.Map$Entry | getFirst()Return the entry for the "oldest" mapping. That is, return the Map.Entry
for the key-value pair that was first put into the map when compared to
all the other pairings in the map. This behavior is equivalent to using
entrySet().iterator().next() , but this method provides an
optimized implementation.
// sentinel.next points to the "first" element of the sequence -- the head
// of the list, which is exactly the entry we need to return. We must test
// for an empty list though because we don't want to return the sentinel!
return (isEmpty()) ? null : sentinel.next;
|
public java.lang.Object | getFirstKey()Return the key for the "oldest" mapping. That is, return the key for the
mapping that was first put into the map when compared to all the other
objects in the map. This behavior is equivalent to using
getFirst().getKey() , but this method provides a slightly
optimized implementation.
// sentinel.next points to the "first" element of the sequence -- the head
// of the list -- and the requisite key is returned from it. An empty list
// does not need to be tested. In cases where the list is empty,
// sentinel.next will point to the sentinel itself which has a null key,
// which is exactly what we would want to return if the list is empty (a
// nice convient way to avoid test for an empty list)
return sentinel.next.getKey();
|
public java.lang.Object | getFirstValue()Return the value for the "oldest" mapping. That is, return the value for
the mapping that was first put into the map when compared to all the
other objects in the map. This behavior is equivalent to using
getFirst().getValue() , but this method provides a slightly
optimized implementation.
// sentinel.next points to the "first" element of the sequence -- the head
// of the list -- and the requisite value is returned from it. An empty
// list does not need to be tested. In cases where the list is empty,
// sentinel.next will point to the sentinel itself which has a null value,
// which is exactly what we would want to return if the list is empty (a
// nice convient way to avoid test for an empty list)
return sentinel.next.getValue();
|
public java.util.Map$Entry | getLast()Return the entry for the "newest" mapping. That is, return the Map.Entry
for the key-value pair that was first put into the map when compared to
all the other pairings in the map. The behavior is equivalent to:
Object obj = null;
Iterator iter = entrySet().iterator();
while(iter.hasNext()) {
obj = iter.next();
}
return (Map.Entry)obj;
However, the implementation of this method ensures an O(1) lookup of the
last key rather than O(n).
// sentinel.prev points to the "last" element of the sequence -- the tail
// of the list, which is exactly the entry we need to return. We must test
// for an empty list though because we don't want to return the sentinel!
return (isEmpty()) ? null : sentinel.prev;
|
public java.lang.Object | getLastKey()Return the key for the "newest" mapping. That is, return the key for the
mapping that was last put into the map when compared to all the other
objects in the map. This behavior is equivalent to using
getLast().getKey() , but this method provides a slightly
optimized implementation.
// sentinel.prev points to the "last" element of the sequence -- the tail
// of the list -- and the requisite key is returned from it. An empty list
// does not need to be tested. In cases where the list is empty,
// sentinel.prev will point to the sentinel itself which has a null key,
// which is exactly what we would want to return if the list is empty (a
// nice convient way to avoid test for an empty list)
return sentinel.prev.getKey();
|
public java.lang.Object | getLastValue()Return the value for the "newest" mapping. That is, return the value for
the mapping that was last put into the map when compared to all the other
objects in the map. This behavior is equivalent to using
getLast().getValue() , but this method provides a slightly
optimized implementation.
// sentinel.prev points to the "last" element of the sequence -- the tail
// of the list -- and the requisite value is returned from it. An empty
// list does not need to be tested. In cases where the list is empty,
// sentinel.prev will point to the sentinel itself which has a null value,
// which is exactly what we would want to return if the list is empty (a
// nice convient way to avoid test for an empty list)
return sentinel.prev.getValue();
|
public java.lang.Object | getValue(int index)Gets the value at the specified index.
return getEntry(index).getValue();
|
public int | hashCode()Implements {@link Map#hashCode()}.
return entrySet().hashCode();
|
public int | indexOf(java.lang.Object key)Gets the index of the specified key.
Entry e = (Entry) entries.get(key);
if (e == null) {
return -1;
}
int pos = 0;
while (e.prev != sentinel) {
pos++;
e = e.prev;
}
return pos;
|
private void | insertEntry(org.apache.axis.collections.SequencedHashMap$Entry entry)Inserts a new internal entry to the tail of the linked list. This does
not add the entry to the underlying map.
entry.next = sentinel;
entry.prev = sentinel.prev;
sentinel.prev.next = entry;
sentinel.prev = entry;
|
public boolean | isEmpty()Implements {@link Map#isEmpty()}.
// for quick check whether the map is entry, we can check the linked list
// and see if there's anything in it.
return sentinel.next == sentinel;
|
public java.util.Iterator | iterator()Gets an iterator over the keys.
return keySet().iterator();
|
public java.util.Set | keySet()Implements {@link Map#keySet()}.
return new AbstractSet() {
// required impls
public Iterator iterator() {
return new OrderedIterator(KEY);
}
public boolean remove(Object o) {
Entry e = SequencedHashMap.this.removeImpl(o);
return (e != null);
}
// more efficient impls than abstract set
public void clear() {
SequencedHashMap.this.clear();
}
public int size() {
return SequencedHashMap.this.size();
}
public boolean isEmpty() {
return SequencedHashMap.this.isEmpty();
}
public boolean contains(Object o) {
return SequencedHashMap.this.containsKey(o);
}
};
|
public int | lastIndexOf(java.lang.Object key)Gets the last index of the specified key.
// keys in a map are guarunteed to be unique
return indexOf(key);
|
public java.lang.Object | put(java.lang.Object key, java.lang.Object value)Implements {@link Map#put(Object, Object)}.
modCount++;
Object oldValue = null;
// lookup the entry for the specified key
Entry e = (Entry) entries.get(key);
// check to see if it already exists
if (e != null) {
// remove from list so the entry gets "moved" to the end of list
removeEntry(e);
// update value in map
oldValue = e.setValue(value);
// Note: We do not update the key here because its unnecessary. We only
// do comparisons using equals(Object) and we know the specified key and
// that in the map are equal in that sense. This may cause a problem if
// someone does not implement their hashCode() and/or equals(Object)
// method properly and then use it as a key in this map.
} else {
// add new entry
e = new Entry(key, value);
entries.put(key, e);
}
// assert(entry in map, but not list)
// add to list
insertEntry(e);
return oldValue;
|
public void | putAll(java.util.Map t)Adds all the mappings in the specified map to this map, replacing any
mappings that already exist (as per {@link Map#putAll(Map)}). The order
in which the entries are added is determined by the iterator returned
from {@link Map#entrySet()} for the specified map.
Iterator iter = t.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
put(entry.getKey(), entry.getValue());
}
|
public void | readExternal(java.io.ObjectInput in)Deserializes this map from the given stream.
int size = in.readInt();
for (int i = 0; i < size; i++) {
Object key = in.readObject();
Object value = in.readObject();
put(key, value);
}
|
public java.lang.Object | remove(java.lang.Object key)Implements {@link Map#remove(Object)}.
Entry e = removeImpl(key);
return (e == null) ? null : e.getValue();
|
public java.lang.Object | remove(int index)Removes the element at the specified index.
return remove(get(index));
|
private void | removeEntry(org.apache.axis.collections.SequencedHashMap$Entry entry)Removes an internal entry from the linked list. This does not remove
it from the underlying map.
entry.next.prev = entry.prev;
entry.prev.next = entry.next;
|
private org.apache.axis.collections.SequencedHashMap$Entry | removeImpl(java.lang.Object key)Fully remove an entry from the map, returning the old entry or null if
there was no such entry with the specified key.
Entry e = (Entry) entries.remove(key);
if (e == null)
return null;
modCount++;
removeEntry(e);
return e;
|
public java.util.List | sequence()Returns a List view of the keys rather than a set view. The returned
list is unmodifiable. This is required because changes to the values of
the list (using {@link java.util.ListIterator#set(Object)}) will
effectively remove the value from the list and reinsert that value at
the end of the list, which is an unexpected side effect of changing the
value of a list. This occurs because changing the key, changes when the
mapping is added to the map and thus where it appears in the list.
An alternative to this method is to use {@link #keySet()}
List l = new ArrayList(size());
Iterator iter = keySet().iterator();
while (iter.hasNext()) {
l.add(iter.next());
}
return Collections.unmodifiableList(l);
|
public int | size()Implements {@link Map#size()}.
// use the underlying Map's size since size is not maintained here.
return entries.size();
|
public java.lang.String | toString()Provides a string representation of the entries within the map. The
format of the returned string may change with different releases, so this
method is suitable for debugging purposes only. If a specific format is
required, use {@link #entrySet()}.{@link Set#iterator() iterator()} and
iterate over the entries in the map formatting them as appropriate.
StringBuffer buf = new StringBuffer();
buf.append('[");
for (Entry pos = sentinel.next; pos != sentinel; pos = pos.next) {
buf.append(pos.getKey());
buf.append('=");
buf.append(pos.getValue());
if (pos.next != sentinel) {
buf.append(',");
}
}
buf.append(']");
return buf.toString();
|
public java.util.Collection | values()Implements {@link Map#values()}.
return new AbstractCollection() {
// required impl
public Iterator iterator() {
return new OrderedIterator(VALUE);
}
public boolean remove(Object value) {
// do null comparison outside loop so we only need to do it once. This
// provides a tighter, more efficient loop at the expense of slight
// code duplication.
if (value == null) {
for (Entry pos = sentinel.next; pos != sentinel; pos = pos.next) {
if (pos.getValue() == null) {
SequencedHashMap.this.removeImpl(pos.getKey());
return true;
}
}
} else {
for (Entry pos = sentinel.next; pos != sentinel; pos = pos.next) {
if (value.equals(pos.getValue())) {
SequencedHashMap.this.removeImpl(pos.getKey());
return true;
}
}
}
return false;
}
// more efficient impls than abstract collection
public void clear() {
SequencedHashMap.this.clear();
}
public int size() {
return SequencedHashMap.this.size();
}
public boolean isEmpty() {
return SequencedHashMap.this.isEmpty();
}
public boolean contains(Object o) {
return SequencedHashMap.this.containsValue(o);
}
};
|
public void | writeExternal(java.io.ObjectOutput out)Serializes this map to the given stream.
out.writeInt(size());
for (Entry pos = sentinel.next; pos != sentinel; pos = pos.next) {
out.writeObject(pos.getKey());
out.writeObject(pos.getValue());
}
|