一、前言
关于apache的commons-collections的org.apache.commons.collections.SequencedHashMap实现了基于java.lang.Map接口,并增强和补充了原有的java.util.HashMap功能,详细参考下面源码说明部分。
二、源码说明
package org.apache.commons.collections;@b@@b@import java.io.DataInput;@b@import java.io.DataOutput;@b@import java.io.Externalizable;@b@import java.io.IOException;@b@import java.io.ObjectInput;@b@import java.io.ObjectOutput;@b@import java.util.AbstractCollection;@b@import java.util.AbstractSet;@b@import java.util.ArrayList;@b@import java.util.Collection;@b@import java.util.ConcurrentModificationException;@b@import java.util.HashMap;@b@import java.util.Iterator;@b@import java.util.List;@b@import java.util.Map;@b@import java.util.Map.Entry;@b@import java.util.NoSuchElementException;@b@import java.util.Set;@b@import org.apache.commons.collections.list.UnmodifiableList;@b@@b@@b@public class SequencedHashMap@b@ implements Map, Cloneable, Externalizable@b@{@b@ private Entry sentinel;@b@ private HashMap entries;@b@ private transient long modCount;@b@ private static final int KEY = 0;@b@ private static final int VALUE = 1;@b@ private static final int ENTRY = 2;@b@ private static final int REMOVED_MASK = -2147483648;@b@ private static final long serialVersionUID = 3380552487888102930L;@b@@b@ private static final Entry createSentinel()@b@ {@b@ Entry s = new Entry(null, null);@b@ s.prev = s;@b@ s.next = s;@b@ return s;@b@ }@b@@b@ public SequencedHashMap()@b@ {@b@ this.modCount = 0L;@b@@b@ this.sentinel = createSentinel();@b@ this.entries = new HashMap();@b@ }@b@@b@ public SequencedHashMap(int initialSize)@b@ {@b@ this.modCount = 0L;@b@@b@ this.sentinel = createSentinel();@b@ this.entries = new HashMap(initialSize);@b@ }@b@@b@ public SequencedHashMap(int initialSize, float loadFactor)@b@ {@b@ this.modCount = 0L;@b@@b@ this.sentinel = createSentinel();@b@ this.entries = new HashMap(initialSize, loadFactor);@b@ }@b@@b@ public SequencedHashMap(Map m)@b@ {@b@ putAll(m);@b@ }@b@@b@ private void removeEntry(Entry entry)@b@ {@b@ entry.next.prev = entry.prev;@b@ entry.prev.next = entry.next;@b@ }@b@@b@ private void insertEntry(Entry entry)@b@ {@b@ entry.next = this.sentinel;@b@ entry.prev = this.sentinel.prev;@b@ this.sentinel.prev.next = entry;@b@ this.sentinel.prev = entry;@b@ }@b@@b@ public int size()@b@ {@b@ return this.entries.size();@b@ }@b@@b@ public boolean isEmpty()@b@ {@b@ return (this.sentinel.next == this.sentinel);@b@ }@b@@b@ public boolean containsKey(Object key)@b@ {@b@ return this.entries.containsKey(key);@b@ }@b@@b@ public boolean containsValue(Object value)@b@ {@b@ Entry pos;@b@ if (value == null)@b@ for (pos = this.sentinel.next; pos != this.sentinel; pos = pos.next)@b@ if (pos.getValue() == null)@b@ return true;@b@@b@ else@b@ for (pos = this.sentinel.next; pos != this.sentinel; pos = pos.next)@b@ if (value.equals(pos.getValue()))@b@ return true;@b@@b@@b@ return false;@b@ }@b@@b@ public Object get(Object o)@b@ {@b@ Entry entry = (Entry)this.entries.get(o);@b@ if (entry == null)@b@ return null;@b@@b@ return entry.getValue();@b@ }@b@@b@ public Map.Entry getFirst()@b@ {@b@ return ((isEmpty()) ? null : this.sentinel.next);@b@ }@b@@b@ public Object getFirstKey()@b@ {@b@ return this.sentinel.next.getKey();@b@ }@b@@b@ public Object getFirstValue()@b@ {@b@ return this.sentinel.next.getValue();@b@ }@b@@b@ public Map.Entry getLast()@b@ {@b@ return ((isEmpty()) ? null : this.sentinel.prev);@b@ }@b@@b@ public Object getLastKey()@b@ {@b@ return this.sentinel.prev.getKey();@b@ }@b@@b@ public Object getLastValue()@b@ {@b@ return this.sentinel.prev.getValue();@b@ }@b@@b@ public Object put(Object key, Object value)@b@ {@b@ this.modCount += 1L;@b@@b@ Object oldValue = null;@b@@b@ Entry e = (Entry)this.entries.get(key);@b@@b@ if (e != null)@b@ {@b@ removeEntry(e);@b@@b@ oldValue = e.setValue(value);@b@ }@b@ else@b@ {@b@ e = new Entry(key, value);@b@ this.entries.put(key, e);@b@ }@b@@b@ insertEntry(e);@b@@b@ return oldValue;@b@ }@b@@b@ public Object remove(Object key)@b@ {@b@ Entry e = removeImpl(key);@b@ return ((e == null) ? null : e.getValue());@b@ }@b@@b@ private Entry removeImpl(Object key)@b@ {@b@ Entry e = (Entry)this.entries.remove(key);@b@ if (e == null)@b@ return null;@b@ this.modCount += 1L;@b@ removeEntry(e);@b@ return e;@b@ }@b@@b@ public void putAll(Map t)@b@ {@b@ Iterator iter = t.entrySet().iterator();@b@ while (iter.hasNext()) {@b@ Map.Entry entry = (Map.Entry)iter.next();@b@ put(entry.getKey(), entry.getValue());@b@ }@b@ }@b@@b@ public void clear()@b@ {@b@ this.modCount += 1L;@b@@b@ this.entries.clear();@b@@b@ this.sentinel.next = this.sentinel;@b@ this.sentinel.prev = this.sentinel;@b@ }@b@@b@ public boolean equals(Object obj)@b@ {@b@ if (obj == null)@b@ return false;@b@ if (obj == this)@b@ return true;@b@@b@ if (!(obj instanceof Externalizable))@b@ return false;@b@@b@ return entrySet().equals(((Externalizable)obj).entrySet());@b@ }@b@@b@ public int hashCode()@b@ {@b@ return entrySet().hashCode();@b@ }@b@@b@ public String toString()@b@ {@b@ StringBuffer buf = new StringBuffer();@b@ buf.append('[');@b@ for (Entry pos = this.sentinel.next; pos != this.sentinel; pos = pos.next) {@b@ buf.append(pos.getKey());@b@ buf.append('=');@b@ buf.append(pos.getValue());@b@ if (pos.next != this.sentinel)@b@ buf.append(',');@b@ }@b@@b@ buf.append(']');@b@@b@ return buf.toString();@b@ }@b@@b@ public Set keySet()@b@ {@b@ return new AbstractSet(this) {@b@ private final SequencedHashMap this$0;@b@@b@ public Iterator iterator() {@b@ return new SequencedHashMap.OrderedIterator(this.this$0, 0); }@b@@b@ public boolean remove() {@b@ SequencedHashMap.Entry e = SequencedHashMap.access$000(this.this$0, o);@b@ return (e != null);@b@ }@b@@b@ public void clear()@b@ {@b@ this.this$0.clear(); }@b@@b@ public int size() {@b@ return this.this$0.size(); }@b@@b@ public boolean isEmpty() {@b@ return this.this$0.isEmpty(); }@b@@b@ public boolean contains() {@b@ return this.this$0.containsKey(o);@b@ }@b@ };@b@ }@b@@b@ public Collection values()@b@ {@b@ return new AbstractCollection(this) {@b@ private final SequencedHashMap this$0;@b@@b@ public Iterator iterator() { return new SequencedHashMap.OrderedIterator(this.this$0, 1);@b@ }@b@@b@ public boolean remove()@b@ {@b@ SequencedHashMap.Entry pos;@b@ if (value == null)@b@ for (pos = SequencedHashMap.access$100(this.this$0).next; pos != SequencedHashMap.access$100(this.this$0); pos = pos.next)@b@ if (pos.getValue() == null) {@b@ SequencedHashMap.access$000(this.this$0, pos.getKey());@b@ return true;@b@ }@b@@b@ else@b@ for (pos = SequencedHashMap.access$100(this.this$0).next; pos != SequencedHashMap.access$100(this.this$0); pos = pos.next)@b@ if (value.equals(pos.getValue())) {@b@ SequencedHashMap.access$000(this.this$0, pos.getKey());@b@ return true;@b@ }@b@@b@@b@@b@ return false;@b@ }@b@@b@ public void clear()@b@ {@b@ this.this$0.clear(); }@b@@b@ public int size() {@b@ return this.this$0.size(); }@b@@b@ public boolean isEmpty() {@b@ return this.this$0.isEmpty(); }@b@@b@ public boolean contains() {@b@ return this.this$0.containsValue(o);@b@ }@b@ };@b@ }@b@@b@ public Set entrySet()@b@ {@b@ return new AbstractSet(this) {@b@ private final SequencedHashMap this$0;@b@@b@ private SequencedHashMap.Entry findEntry() { if (o == null)@b@ return null;@b@ if (!(o instanceof Map.Entry))@b@ return null;@b@@b@ Map.Entry e = (Map.Entry)o;@b@ SequencedHashMap.Entry entry = (SequencedHashMap.Entry)SequencedHashMap.access$200(this.this$0).get(e.getKey());@b@ if ((entry != null) && (entry.equals(e)))@b@ return entry;@b@@b@ return null;@b@ }@b@@b@ public Iterator iterator()@b@ {@b@ return new SequencedHashMap.OrderedIterator(this.this$0, 2); }@b@@b@ public boolean remove() {@b@ SequencedHashMap.Entry e = findEntry(o);@b@ if (e == null)@b@ return false;@b@@b@ return (SequencedHashMap.access$000(this.this$0, e.getKey()) != null);@b@ }@b@@b@ public void clear()@b@ {@b@ this.this$0.clear(); }@b@@b@ public int size() {@b@ return this.this$0.size(); }@b@@b@ public boolean isEmpty() {@b@ return this.this$0.isEmpty(); }@b@@b@ public boolean contains() {@b@ return (findEntry(o) != null);@b@ }@b@ };@b@ }@b@@b@ public Object clone()@b@ throws CloneNotSupportedException@b@ {@b@ SequencedHashMap map = (SequencedHashMap)super.clone();@b@@b@ map.sentinel = createSentinel();@b@@b@ map.entries = new HashMap();@b@@b@ map.putAll(this);@b@@b@ return map;@b@ }@b@@b@ private Map.Entry getEntry(int index)@b@ {@b@ Entry pos = this.sentinel;@b@@b@ if (index < 0) {@b@ throw new ArrayIndexOutOfBoundsException(index + " < 0");@b@ }@b@@b@ int i = -1;@b@ while ((i < index - 1) && (pos.next != this.sentinel)) {@b@ ++i;@b@ pos = pos.next;@b@ }@b@@b@ if (pos.next == this.sentinel) {@b@ throw new ArrayIndexOutOfBoundsException(index + " >= " + (i + 1));@b@ }@b@@b@ return pos.next;@b@ }@b@@b@ public Object get(int index)@b@ {@b@ return getEntry(index).getKey();@b@ }@b@@b@ public Object getValue(int index)@b@ {@b@ return getEntry(index).getValue();@b@ }@b@@b@ public int indexOf(Object key)@b@ {@b@ Entry e = (Entry)this.entries.get(key);@b@ if (e == null)@b@ return -1;@b@@b@ int pos = 0;@b@ while (e.prev != this.sentinel) {@b@ ++pos;@b@ e = e.prev;@b@ }@b@ return pos;@b@ }@b@@b@ public Iterator iterator()@b@ {@b@ return keySet().iterator();@b@ }@b@@b@ public int lastIndexOf(Object key)@b@ {@b@ return indexOf(key);@b@ }@b@@b@ public List sequence()@b@ {@b@ List l = new ArrayList(size());@b@ Iterator iter = keySet().iterator();@b@ while (iter.hasNext()) {@b@ l.add(iter.next());@b@ }@b@@b@ return UnmodifiableList.decorate(l);@b@ }@b@@b@ public Object remove(int index)@b@ {@b@ return remove(get(index));@b@ }@b@@b@ public void readExternal(ObjectInput in)@b@ throws IOException, ClassNotFoundException@b@ {@b@ int size = in.readInt();@b@ for (int i = 0; i < size; ++i) {@b@ Object key = in.readObject();@b@ Object value = in.readObject();@b@ put(key, value);@b@ }@b@ }@b@@b@ public void writeExternal(ObjectOutput out)@b@ throws IOException@b@ {@b@ out.writeInt(size());@b@ for (Entry pos = this.sentinel.next; pos != this.sentinel; pos = pos.next) {@b@ out.writeObject(pos.getKey());@b@ out.writeObject(pos.getValue());@b@ }@b@ }@b@@b@ static Entry access$000(SequencedHashMap x0, Object x1)@b@ {@b@ return x0.removeImpl(x1); } @b@ static Entry access$100(SequencedHashMap x0) { return x0.sentinel; } @b@ static HashMap access$200(SequencedHashMap x0) { return x0.entries; } @b@ static long access$300(SequencedHashMap x0) { return x0.modCount;@b@ }@b@@b@ private class OrderedIterator@b@ implements Iterator@b@ {@b@ private int returnType;@b@ private SequencedHashMap.Entry pos;@b@ private transient long expectedModCount;@b@ private final SequencedHashMap this$0;@b@@b@ public OrderedIterator(, int returnType)@b@ {@b@ this.this$0 = this$0;@b@@b@ this.pos = SequencedHashMap.access$100(this.this$0);@b@@b@ this.expectedModCount = SequencedHashMap.access$300(this.this$0);@b@@b@ this.returnType = (returnType | 0x80000000);@b@ }@b@@b@ public boolean hasNext()@b@ {@b@ return (this.pos.next != SequencedHashMap.access$100(this.this$0));@b@ }@b@@b@ public Object next()@b@ {@b@ if (SequencedHashMap.access$300(this.this$0) != this.expectedModCount)@b@ throw new ConcurrentModificationException();@b@@b@ if (this.pos.next == SequencedHashMap.access$100(this.this$0)) {@b@ throw new NoSuchElementException();@b@ }@b@@b@ this.returnType &= 2147483647;@b@@b@ this.pos = this.pos.next;@b@ switch (this.returnType)@b@ {@b@ case 0:@b@ return this.pos.getKey();@b@ case 1:@b@ return this.pos.getValue();@b@ case 2:@b@ return this.pos;@b@ }@b@@b@ throw new Error("bad iterator type: " + this.returnType);@b@ }@b@@b@ public void remove()@b@ {@b@ if ((this.returnType & 0x80000000) != 0)@b@ throw new IllegalStateException("remove() must follow next()");@b@@b@ if (SequencedHashMap.access$300(this.this$0) != this.expectedModCount) {@b@ throw new ConcurrentModificationException();@b@ }@b@@b@ SequencedHashMap.access$000(this.this$0, this.pos.getKey());@b@@b@ this.expectedModCount += 1L;@b@@b@ this.returnType |= -2147483648;@b@ }@b@ }@b@@b@ private static class Entry@b@ implements Map.Entry, KeyValue@b@ {@b@ private final Object key;@b@ private Object value;@b@ Entry next = null;@b@ Entry prev = null;@b@@b@ public Entry(Object key, Object value)@b@ {@b@ this.key = key;@b@ this.value = value;@b@ }@b@@b@ public Object getKey()@b@ {@b@ return this.key;@b@ }@b@@b@ public Object getValue()@b@ {@b@ return this.value;@b@ }@b@@b@ public Object setValue(Object value)@b@ {@b@ Object oldValue = this.value;@b@ this.value = value;@b@ return oldValue;@b@ }@b@@b@ public int hashCode()@b@ {@b@ return (((getKey() == null) ? 0 : getKey().hashCode()) ^ ((getValue() == null) ? 0 : getValue().hashCode()));@b@ }@b@@b@ public boolean equals(Object obj) {@b@ if (obj == null)@b@ return false;@b@ if (obj == this)@b@ return true;@b@ if (!(obj instanceof KeyValue))@b@ return false;@b@@b@ Map.Entry other = (KeyValue)obj;@b@@b@ if (((getKey() == null) ? false : (other.getKey() == null) ? true : getKey().equals(other.getKey())));@b@ return (((getValue() == null) ? false : (other.getValue() == null) ? true : getValue().equals(other.getValue())));@b@ }@b@@b@ public String toString()@b@ {@b@ return "[" + getKey() + "=" + getValue() + "]";@b@ }@b@ }@b@}
2.UnmodifiableList
package org.apache.commons.collections.list;@b@@b@import java.util.Collection;@b@import java.util.Iterator;@b@import java.util.List;@b@import java.util.ListIterator;@b@import org.apache.commons.collections.Unmodifiable;@b@import org.apache.commons.collections.collection.AbstractCollectionDecorator;@b@import org.apache.commons.collections.iterators.UnmodifiableIterator;@b@import org.apache.commons.collections.iterators.UnmodifiableListIterator;@b@@b@public final class UnmodifiableList extends AbstractSerializableListDecorator@b@ implements Unmodifiable@b@{@b@ private static final long serialVersionUID = 6595182819922443652L;@b@@b@ public static List decorate(List list)@b@ {@b@ if (list instanceof Unmodifiable)@b@ return list;@b@@b@ return new UnmodifiableList(list);@b@ }@b@@b@ private UnmodifiableList(List list)@b@ {@b@ super(list);@b@ }@b@@b@ public Iterator iterator()@b@ {@b@ return UnmodifiableIterator.decorate(getCollection().iterator());@b@ }@b@@b@ public boolean add(Object object) {@b@ throw new UnsupportedOperationException();@b@ }@b@@b@ public boolean addAll(Collection coll) {@b@ throw new UnsupportedOperationException();@b@ }@b@@b@ public void clear() {@b@ throw new UnsupportedOperationException();@b@ }@b@@b@ public boolean remove(Object object) {@b@ throw new UnsupportedOperationException();@b@ }@b@@b@ public boolean removeAll(Collection coll) {@b@ throw new UnsupportedOperationException();@b@ }@b@@b@ public boolean retainAll(Collection coll) {@b@ throw new UnsupportedOperationException();@b@ }@b@@b@ public ListIterator listIterator()@b@ {@b@ return UnmodifiableListIterator.decorate(getList().listIterator());@b@ }@b@@b@ public ListIterator listIterator(int index) {@b@ return UnmodifiableListIterator.decorate(getList().listIterator(index));@b@ }@b@@b@ public void add(int index, Object object) {@b@ throw new UnsupportedOperationException();@b@ }@b@@b@ public boolean addAll(int index, Collection coll) {@b@ throw new UnsupportedOperationException();@b@ }@b@@b@ public Object remove(int index) {@b@ throw new UnsupportedOperationException();@b@ }@b@@b@ public Object set(int index, Object object) {@b@ throw new UnsupportedOperationException();@b@ }@b@@b@ public List subList(int fromIndex, int toIndex) {@b@ List sub = getList().subList(fromIndex, toIndex);@b@ return new UnmodifiableList(sub);@b@ }@b@}