📄 staticbucketmap.java
字号:
* @return the key set
*/
public Set keySet() {
return new KeySet();
}
/**
* Gets the values.
*
* @return the values
*/
public Collection values() {
return new Values();
}
/**
* Gets the entry set.
*
* @return the entry set
*/
public Set entrySet() {
return new EntrySet();
}
//-----------------------------------------------------------------------
/**
* Puts all the entries from the specified map into this map.
* This operation is <b>not atomic</b> and may have undesired effects.
*
* @param map the map of entries to add
*/
public void putAll(Map map) {
Iterator i = map.keySet().iterator();
while (i.hasNext()) {
Object key = i.next();
put(key, map.get(key));
}
}
/**
* Clears the map of all entries.
*/
public void clear() {
for (int i = 0; i < buckets.length; i++) {
Lock lock = locks[i];
synchronized (lock) {
buckets[i] = null;
lock.size = 0;
}
}
}
/**
* Compares this map to another, as per the Map specification.
*
* @param obj the object to compare to
* @return true if equal
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Map == false) {
return false;
}
Map other = (Map) obj;
return entrySet().equals(other.entrySet());
}
/**
* Gets the hash code, as per the Map specification.
*
* @return the hash code
*/
public int hashCode() {
int hashCode = 0;
for (int i = 0; i < buckets.length; i++) {
synchronized (locks[i]) {
Node n = buckets[i];
while (n != null) {
hashCode += n.hashCode();
n = n.next;
}
}
}
return hashCode;
}
//-----------------------------------------------------------------------
/**
* The Map.Entry for the StaticBucketMap.
*/
private static final class Node implements Map.Entry, KeyValue {
protected Object key;
protected Object value;
protected Node next;
public Object getKey() {
return key;
}
public Object getValue() {
return value;
}
public int hashCode() {
return ((key == null ? 0 : key.hashCode()) ^
(value == null ? 0 : value.hashCode()));
}
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Map.Entry == false) {
return false;
}
Map.Entry e2 = (Map.Entry) obj;
return (
(key == null ? e2.getKey() == null : key.equals(e2.getKey())) &&
(value == null ? e2.getValue() == null : value.equals(e2.getValue())));
}
public Object setValue(Object obj) {
Object retVal = value;
value = obj;
return retVal;
}
}
/**
* The lock object, which also includes a count of the nodes in this lock.
*/
private final static class Lock {
public int size;
}
//-----------------------------------------------------------------------
private class EntryIterator implements Iterator {
private ArrayList current = new ArrayList();
private int bucket;
private Map.Entry last;
public boolean hasNext() {
if (current.size() > 0) return true;
while (bucket < buckets.length) {
synchronized (locks[bucket]) {
Node n = buckets[bucket];
while (n != null) {
current.add(n);
n = n.next;
}
bucket++;
if (current.size() > 0) return true;
}
}
return false;
}
protected Map.Entry nextEntry() {
if (!hasNext()) throw new NoSuchElementException();
last = (Map.Entry)current.remove(current.size() - 1);
return last;
}
public Object next() {
return nextEntry();
}
public void remove() {
if (last == null) throw new IllegalStateException();
StaticBucketMap.this.remove(last.getKey());
last = null;
}
}
private class ValueIterator extends EntryIterator {
public Object next() {
return nextEntry().getValue();
}
}
private class KeyIterator extends EntryIterator {
public Object next() {
return nextEntry().getKey();
}
}
private class EntrySet extends AbstractSet {
public int size() {
return StaticBucketMap.this.size();
}
public void clear() {
StaticBucketMap.this.clear();
}
public Iterator iterator() {
return new EntryIterator();
}
public boolean contains(Object obj) {
Map.Entry entry = (Map.Entry) obj;
int hash = getHash(entry.getKey());
synchronized (locks[hash]) {
for (Node n = buckets[hash]; n != null; n = n.next) {
if (n.equals(entry)) return true;
}
}
return false;
}
public boolean remove(Object obj) {
if (obj instanceof Map.Entry == false) {
return false;
}
Map.Entry entry = (Map.Entry) obj;
int hash = getHash(entry.getKey());
synchronized (locks[hash]) {
for (Node n = buckets[hash]; n != null; n = n.next) {
if (n.equals(entry)) {
StaticBucketMap.this.remove(n.getKey());
return true;
}
}
}
return false;
}
}
private class KeySet extends AbstractSet {
public int size() {
return StaticBucketMap.this.size();
}
public void clear() {
StaticBucketMap.this.clear();
}
public Iterator iterator() {
return new KeyIterator();
}
public boolean contains(Object obj) {
return StaticBucketMap.this.containsKey(obj);
}
public boolean remove(Object obj) {
int hash = getHash(obj);
synchronized (locks[hash]) {
for (Node n = buckets[hash]; n != null; n = n.next) {
Object k = n.getKey();
if ((k == obj) || ((k != null) && k.equals(obj))) {
StaticBucketMap.this.remove(k);
return true;
}
}
}
return false;
}
}
private class Values extends AbstractCollection {
public int size() {
return StaticBucketMap.this.size();
}
public void clear() {
StaticBucketMap.this.clear();
}
public Iterator iterator() {
return new ValueIterator();
}
}
/**
* Prevents any operations from occurring on this map while the
* given {@link Runnable} executes. This method can be used, for
* instance, to execute a bulk operation atomically:
*
* <pre>
* staticBucketMapInstance.atomic(new Runnable() {
* public void run() {
* staticBucketMapInstance.putAll(map);
* }
* });
* </pre>
*
* It can also be used if you need a reliable iterator:
*
* <pre>
* staticBucketMapInstance.atomic(new Runnable() {
* public void run() {
* Iterator iterator = staticBucketMapInstance.iterator();
* while (iterator.hasNext()) {
* foo(iterator.next();
* }
* }
* });
* </pre>
*
* <b>Implementation note:</b> This method requires a lot of time
* and a ton of stack space. Essentially a recursive algorithm is used
* to enter each bucket's monitor. If you have twenty thousand buckets
* in your map, then the recursive method will be invoked twenty thousand
* times. You have been warned.
*
* @param r the code to execute atomically
*/
public void atomic(Runnable r) {
if (r == null) throw new NullPointerException();
atomic(r, 0);
}
private void atomic(Runnable r, int bucket) {
if (bucket >= buckets.length) {
r.run();
return;
}
synchronized (locks[bucket]) {
atomic(r, bucket + 1);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -