📄 cachemap.java
字号:
_lifetime = lifetime; return this; } /** * Gets the maximal allowed size. Defalut: {@link #DEFAULT_MAXSIZE}. * An mapping won't be removed by GC unless the minimal lifetime * or the maximal allowed size exceeds. * @see #getLifetime */ public int getMaxSize() { return _maxsize; } /** * Sets the maximal allowed size. * @see #getMaxSize */ public CacheMap setMaxSize(int maxsize) { _maxsize = maxsize; return this; } /** * Gets the last accessed time, in system millisecs. * @return the last accessed time; 0 if not found */ /* To support this method, we cannot use access-ordered for _map Then, get() and put() shall use remove and add public final long getLastAccessTime(Object key) { final Value v = (Value)_map.get(key); return v != null ? v.access: 0; }*/ //-- Map --// public boolean isEmpty() { expunge(); return _map.isEmpty(); } public int size() { expunge(); return _map.size(); } public void clear() { _map.clear(); } public Object remove(Object key) { expunge(); final Value v = (Value)_map.remove(key); return v != null ? v.value: null; } public Object get(Object key) { expunge(); return getWithoutExpunge(key); } /** Returns the value without trying to expunge first. * It is useful if you want to preserve all entries. */ public Object getWithoutExpunge(Object key) { final Value v = (Value)_map.get(key); //re-order if (v != null) { v.updateAccessTime(); //assertion(key); return v.value; } return null; } public boolean containsKey(Object key) { expunge(); return _map.containsKey(key); } public boolean containsValue(Object value) { expunge(); for (final Iterator it = _map.values().iterator(); it.hasNext();) { final Value v = (Value)it.next(); if (Objects.equals(v.value, value)) return true; } return false; } public Object put(Object key, Object value) { expunge(); final Value v = (Value)_map.put(key, new Value(value)); return v != null ? v.value: null; } public void putAll(Map map) { for (final Iterator it = map.entrySet().iterator(); it.hasNext();) { final Map.Entry me = (Map.Entry)it.next(); put(me.getKey(), me.getValue()); } } /** It wraps what is stored in _map, such that the caller * won't know the value is wrapped with Value. */ private class Entry implements Map.Entry { final Map.Entry _me; private Entry(Map.Entry me) { _me = me; } public Object getKey() { return _me.getKey(); } public Object getValue() { return ((Value)_me.getValue()).value; } public Object setValue(Object o) { assert(!(o instanceof Value)); //we don't re-order it to avoid comodification error final Value v = (Value)_me.getValue(); final Object old = v.value; v.value = o; return old; } //-- Object --// public int hashCode() { return _me.hashCode(); } public boolean equals(Object o) { return (o instanceof Entry) && _me.equals(((Entry)o)._me); } } /** Abstract iterator. */ private class KeyIter implements Iterator { protected Iterator _it; private KeyIter(Iterator it) { _it = it; } public boolean hasNext() { return _it.hasNext(); } public void remove() { _it.remove(); //remove from map } public Object next() { return _it.next(); } } /** Entry iterator. Don't call expunge to avoid co-modified exception. */ private class EntryIter extends KeyIter { private EntryIter(Iterator it) { super(it); } public Object next() { return new Entry((Map.Entry)_it.next()); } } /** The entry set. */ private class EntrySet extends AbstractSet { private EntrySet() { } //-- Set --// public Iterator iterator() { expunge(); return new EntryIter(_map.entrySet().iterator()); } public boolean contains(Object o) { return (o instanceof Map.Entry) && CacheMap.this.containsKey(((Map.Entry)o).getKey()); } public boolean remove(Object o) { return (o instanceof Map.Entry) && CacheMap.this.remove(((Map.Entry)o).getKey()) != null; } public int size() { return CacheMap.this.size(); } public void clear() { CacheMap.this.clear(); } } public Set entrySet() { expunge(); return new EntrySet(); } /** The entry set. */ private class KeySet extends AbstractSet { private KeySet() { } //-- Set --// public Iterator iterator() { expunge(); return new KeyIter(_map.keySet().iterator()); } public boolean contains(Object o) { return CacheMap.this.containsKey(o); } public boolean remove(Object o) { return CacheMap.this.remove(o) != null; } public int size() { return CacheMap.this.size(); } public void clear() { CacheMap.this.clear(); } } public Set keySet() { expunge(); return new KeySet(); } /** Value iterator. Don't call expunge to avoid co-modified exception. */ private class ValueIter extends KeyIter { private ValueIter(Iterator it) { super(it); } public Object next() { return ((Value)_it.next()).value; } } /** The value collection. */ private class Values extends AbstractCollection { public Iterator iterator() { return new ValueIter(_map.values().iterator()); } public int size() { return CacheMap.this.size(); } public boolean contains(Object o) { return CacheMap.this.containsValue(o); } public void clear() { CacheMap.this.clear(); } } public Collection values() { expunge(); return new Values(); } //-- Object --// public int hashCode() { expunge(); return _map.hashCode(); } public boolean equals(Object o) { expunge(); return o == this || ((o instanceof CacheMap) && _map.equals(((CacheMap)o)._map)) || ((o instanceof Map) && _map.equals((Map)o)); } public String toString() { expunge(); final StringBuffer sb = new StringBuffer(128).append('{'); if (!_map.isEmpty()) { for (final Iterator it = _map.entrySet().iterator();;) { final Map.Entry me = (Map.Entry)it.next(); sb.append(me.getKey()).append('=') .append(Objects.toString(((Value)me.getValue()).value)); if (it.hasNext()) sb.append(", "); else break; //done } } return sb.append('}').toString(); } //-- Debug --// /** To make sure that it is in the acess order. */ /*private final void assertion(Object key) { long last = Long.MIN_VALUE; int j = 0; for (final Iterator it = _map.values().iterator(); it.hasNext(); ++j) { final Value v = (Value)it.next(); assert v.access >= last: "Order is wrong: j="+j+" key="+key+" acs="+v.access+" map="+_map; last = v.access; } }*/ //Cloneable// public Object clone() { final CacheMap clone; try { clone = (CacheMap)super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } clone._map = new LinkedHashMap(clone._map); for (Iterator it = clone._map.entrySet().iterator(); it.hasNext();) { final Map.Entry me = (Map.Entry)it.next(); me.setValue(((Value)me.getValue()).clone()); } clone.init(); return clone; } //Serializable// //NOTE: they must be declared as private private synchronized void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { s.defaultWriteObject(); } private synchronized void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); init(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -