📄 staticbucketmap.java
字号:
synchronized( m_locks[ hash ] )
{
Node n = m_buckets[ hash ];
Node prev = null;
while( n != null )
{
if( n.key == key || ( n.key != null && n.key.equals( key ) ) )
{
// Remove this node from the linked list of nodes.
if( null == prev )
{
// This node was the head, set the next node to be the new head.
m_buckets[ hash ] = n.next;
}
else
{
// Set the next node of the previous node to be the node after this one.
prev.next = n.next;
}
m_locks[hash].size--;
return n.value;
}
prev = n;
n = n.next;
}
}
return null;
}
/**
* Implements {@link Map#isEmpty()}.
*/
public final boolean isEmpty()
{
return size() == 0;
}
/**
* Implements {@link Map#clear()}.
*/
public final void clear()
{
for( int i = 0; i < m_buckets.length; i++ )
{
Lock lock = m_locks[i];
synchronized (lock) {
m_buckets[ i ] = null;
lock.size = 0;
}
}
}
/**
* Implements {@link Map#equals(Object)}.
*/
public final boolean equals( Object obj )
{
if( obj == null ) return false;
if( obj == this ) return true;
if( !( obj instanceof Map ) ) return false;
Map other = (Map)obj;
return entrySet().equals(other.entrySet());
}
/**
* Implements {@link Map#hashCode()}.
*/
public final int hashCode()
{
int hashCode = 0;
for( int i = 0; i < m_buckets.length; i++ )
{
synchronized( m_locks[ i ] )
{
Node n = m_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 o) {
if( o == null ) return false;
if( o == this ) return true;
if ( ! (o instanceof Map.Entry ) )
return false;
Map.Entry e2 = (Map.Entry)o;
return ((key == null ?
e2.getKey() == null : key.equals(e2.getKey())) &&
(value == null ?
e2.getValue() == null : value.equals(e2.getValue())));
}
public Object setValue( Object val )
{
Object retVal = value;
value = val;
return retVal;
}
}
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 < m_buckets.length) {
synchronized (m_locks[bucket]) {
Node n = m_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 o) {
Map.Entry entry = (Map.Entry)o;
int hash = getHash(entry.getKey());
synchronized (m_locks[hash]) {
for (Node n = m_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 (m_locks[hash]) {
for (Node n = m_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 o) {
return StaticBucketMap.this.containsKey(o);
}
public boolean remove(Object o) {
int hash = getHash(o);
synchronized (m_locks[hash]) {
for (Node n = m_buckets[hash]; n != null; n = n.next) {
Object k = n.getKey();
if ((k == o) || ((k != null) && k.equals(o))) {
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 >= m_buckets.length) {
r.run();
return;
}
synchronized (m_locks[bucket]) {
atomic(r, bucket + 1);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -