git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1096 379699f6-c40d-0410-875b-85095c16579ebranch_1_1
parent
996fc49dbd
commit
dcd5686bc2
@ -0,0 +1,240 @@ |
||||
package jode.util; |
||||
///#ifdef JDK12
|
||||
///import java.lang.ref.WeakReference;
|
||||
///import java.lang.ref.ReferenceQueue;
|
||||
///#endif
|
||||
|
||||
import @COLLECTIONS@.Comparator; |
||||
import @COLLECTIONS@.AbstractCollection; |
||||
import @COLLECTIONS@.Iterator; |
||||
import @COLLECTIONS@.NoSuchElementException; |
||||
import @COLLECTIONS@.ConcurrentModificationException; |
||||
import @COLLECTIONEXTRA@.UnsupportedOperationException; |
||||
|
||||
public class UnifyHash extends AbstractCollection { |
||||
/** |
||||
* the default capacity |
||||
*/ |
||||
private static final int DEFAULT_CAPACITY = 11; |
||||
|
||||
/** the default load factor of a HashMap */ |
||||
private static final float DEFAULT_LOAD_FACTOR = 0.75F; |
||||
|
||||
///#ifdef JDK12
|
||||
/// private ReferenceQueue queue = new ReferenceQueue();
|
||||
///#endif
|
||||
|
||||
static class Bucket |
||||
///#ifdef JDK12
|
||||
/// extends WeakReference
|
||||
///#endif
|
||||
{ |
||||
///#ifdef JDK12
|
||||
/// public Bucket(Object o, ReferenceQueue q) {
|
||||
/// super(o, q);
|
||||
/// }
|
||||
///#else
|
||||
public Bucket(Object o) { |
||||
this.obj = o; |
||||
} |
||||
|
||||
Object obj; |
||||
|
||||
public Object get() { |
||||
return obj; |
||||
} |
||||
///#endif
|
||||
|
||||
int hash; |
||||
Bucket next; |
||||
} |
||||
|
||||
private Bucket[] buckets; |
||||
int modCount = 0; |
||||
int size = 0; |
||||
int threshold; |
||||
float loadFactor; |
||||
|
||||
public UnifyHash(int initialCapacity, float loadFactor) { |
||||
this.loadFactor = loadFactor; |
||||
buckets = new Bucket[initialCapacity]; |
||||
threshold = (int) (loadFactor * initialCapacity); |
||||
} |
||||
|
||||
public UnifyHash(int initialCapacity) { |
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR); |
||||
} |
||||
|
||||
public UnifyHash() { |
||||
this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR); |
||||
} |
||||
|
||||
private void grow() { |
||||
Bucket[] oldBuckets = buckets; |
||||
int newCap = buckets.length * 2 + 1; |
||||
threshold = (int) (loadFactor * newCap); |
||||
buckets = new Bucket[newCap]; |
||||
for (int i = 0; i < oldBuckets.length; i++) { |
||||
Bucket nextBucket; |
||||
for (Bucket b = oldBuckets[i]; b != null; b = nextBucket) { |
||||
if (i != Math.abs(b.hash % oldBuckets.length)) |
||||
throw new RuntimeException(""+i+", hash: "+b.hash+", oldlength: "+oldBuckets.length); |
||||
int newSlot = Math.abs(b.hash % newCap); |
||||
nextBucket = b.next; |
||||
b.next = buckets[newSlot]; |
||||
buckets[newSlot] = b; |
||||
} |
||||
} |
||||
} |
||||
|
||||
///#ifdef JDK12
|
||||
/// public final void cleanUp() {
|
||||
/// Bucket died;
|
||||
/// while ((died = (Bucket)queue.poll()) != null) {
|
||||
/// int diedSlot = Math.abs(died.hash % buckets.length);
|
||||
/// if (buckets[diedSlot] == died)
|
||||
/// buckets[diedSlot] = died.next;
|
||||
/// else {
|
||||
/// Bucket b = buckets[diedSlot]
|
||||
/// while (b.next != died)
|
||||
/// b = b.next;
|
||||
/// b.next = died.next;
|
||||
/// }
|
||||
/// size--;
|
||||
/// }
|
||||
/// }
|
||||
///#endif
|
||||
|
||||
|
||||
public int size() { |
||||
return size; |
||||
} |
||||
|
||||
public Iterator iterator() { |
||||
///#ifdef JDK12
|
||||
/// cleanUp();
|
||||
///#endif
|
||||
|
||||
return new Iterator() { |
||||
private int bucket = 0; |
||||
private int known = modCount; |
||||
private Bucket nextBucket; |
||||
private Object nextVal; |
||||
|
||||
{ |
||||
internalNext(); |
||||
} |
||||
|
||||
private void internalNext() { |
||||
while (true) { |
||||
while (nextBucket == null) { |
||||
if (bucket == buckets.length) |
||||
return; |
||||
nextBucket = buckets[bucket++]; |
||||
} |
||||
|
||||
nextVal = nextBucket.get(); |
||||
if (nextVal != null) |
||||
return; |
||||
|
||||
nextBucket = nextBucket.next; |
||||
} |
||||
} |
||||
|
||||
public boolean hasNext() { |
||||
return nextBucket != null; |
||||
} |
||||
|
||||
public Object next() { |
||||
if (known != modCount) |
||||
throw new ConcurrentModificationException(); |
||||
if (nextBucket == null) |
||||
throw new NoSuchElementException(); |
||||
Object result = nextVal; |
||||
nextBucket = nextBucket.next; |
||||
internalNext(); |
||||
return result; |
||||
} |
||||
|
||||
public void remove() { |
||||
throw new UnsupportedOperationException(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
public Iterator iterateHashCode(final int hash) { |
||||
return new Iterator() { |
||||
private int known = modCount; |
||||
private Bucket nextBucket |
||||
= buckets[Math.abs(hash % buckets.length)]; |
||||
private Object nextVal; |
||||
|
||||
{ |
||||
internalNext(); |
||||
} |
||||
|
||||
private void internalNext() { |
||||
while (nextBucket != null) { |
||||
if (nextBucket.hash == hash) { |
||||
nextVal = nextBucket.get(); |
||||
if (nextVal != null) |
||||
return; |
||||
} |
||||
|
||||
nextBucket = nextBucket.next; |
||||
} |
||||
} |
||||
|
||||
public boolean hasNext() { |
||||
return nextBucket != null; |
||||
} |
||||
|
||||
public Object next() { |
||||
if (known != modCount) |
||||
throw new ConcurrentModificationException(); |
||||
if (nextBucket == null) |
||||
throw new NoSuchElementException(); |
||||
Object result = nextVal; |
||||
nextBucket = nextBucket.next; |
||||
internalNext(); |
||||
return result; |
||||
} |
||||
|
||||
public void remove() { |
||||
throw new UnsupportedOperationException(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
public void put(int hash, Object o) { |
||||
if (size++ > threshold) |
||||
grow(); |
||||
modCount++; |
||||
|
||||
int slot = Math.abs(hash % buckets.length); |
||||
///#ifdef JDK12
|
||||
/// Bucket b = new Bucket(o, queue);
|
||||
///#else
|
||||
Bucket b = new Bucket(o); |
||||
///#endif
|
||||
b.hash = hash; |
||||
b.next = buckets[slot]; |
||||
buckets[slot] = b; |
||||
} |
||||
|
||||
public Object unify(Object o, int hash, Comparator comparator) { |
||||
///#ifdef JDK12
|
||||
/// cleanUp();
|
||||
///#endif
|
||||
int slot = Math.abs(hash % buckets.length); |
||||
for (Bucket b = buckets[slot]; b != null; b = b.next) { |
||||
Object old = b.get(); |
||||
if (old != null && comparator.compare(o, old) == 0) |
||||
return old; |
||||
} |
||||
|
||||
put(hash, o); |
||||
return o; |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue