Reworked IntMap to be a proper Java collection in the style that the
java.util collections established. This means that IntMap becomes HashIntMap, IntMap is now an interface that extends the standard Map interface and a new Collections class is provided that allows one to create a synchronized wrapper around an IntMap. git-svn-id: https://samskivert.googlecode.com/svn/trunk@318 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: UserRepository.java,v 1.15 2001/08/12 01:34:31 mdb Exp $
|
// $Id: UserRepository.java,v 1.16 2001/09/15 17:22:11 mdb Exp $
|
||||||
//
|
//
|
||||||
// samskivert library - useful routines for java programs
|
// samskivert library - useful routines for java programs
|
||||||
// Copyright (C) 2001 Michael Bayne
|
// Copyright (C) 2001 Michael Bayne
|
||||||
@@ -31,7 +31,7 @@ import com.samskivert.Log;
|
|||||||
import com.samskivert.jdbc.JDBCUtil;
|
import com.samskivert.jdbc.JDBCUtil;
|
||||||
import com.samskivert.jdbc.MySQLRepository;
|
import com.samskivert.jdbc.MySQLRepository;
|
||||||
import com.samskivert.jdbc.jora.*;
|
import com.samskivert.jdbc.jora.*;
|
||||||
import com.samskivert.util.IntMap;
|
import com.samskivert.util.HashIntMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interfaces with the RDBMS in which the user information is stored. The
|
* Interfaces with the RDBMS in which the user information is stored. The
|
||||||
@@ -334,7 +334,7 @@ public class UserRepository extends MySQLRepository
|
|||||||
ids.append(userids[i]);
|
ids.append(userids[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
final IntMap map = new IntMap();
|
final HashIntMap map = new HashIntMap();
|
||||||
|
|
||||||
// do the query
|
// do the query
|
||||||
execute(new Operation () {
|
execute(new Operation () {
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
//
|
||||||
|
// $Id: Collections.java,v 1.1 2001/09/15 17:22:11 mdb Exp $
|
||||||
|
|
||||||
|
package com.samskivert.util;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like the <code>java.util</code> class of the same name, the
|
||||||
|
* <code>Collections</code> class provides utility functions related to
|
||||||
|
* the collections provided by the <code>com.samskivert.util</code>
|
||||||
|
* package.
|
||||||
|
*/
|
||||||
|
public class Collections
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a synchronized (thread-safe) int map backed by the
|
||||||
|
* specified int map. In order to guarantee serial access, it is
|
||||||
|
* critical that <strong>all</strong> access to the backing int map is
|
||||||
|
* accomplished through the returned int map.
|
||||||
|
*
|
||||||
|
* <p> It is imperative that the user manually synchronize on the
|
||||||
|
* returned int map when iterating over any of its collection views:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* IntMap m = Collections.synchronizedIntMap(new HashIntMap());
|
||||||
|
* ...
|
||||||
|
* Set s = m.keySet(); // Needn't be in synchronized block
|
||||||
|
* ...
|
||||||
|
* synchronized(m) { // Synchronizing on m, not s!
|
||||||
|
* Iterator i = s.iterator(); // Must be in synchronized block
|
||||||
|
* while (i.hasNext())
|
||||||
|
* foo(i.next());
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Failure to follow this advice may result in non-deterministic
|
||||||
|
* behavior.
|
||||||
|
*
|
||||||
|
* <p> The returned map will be serializable if the specified map is
|
||||||
|
* serializable.
|
||||||
|
*
|
||||||
|
* @param m the int map to be "wrapped" in a synchronized int map.
|
||||||
|
*
|
||||||
|
* @return a synchronized view of the specified int map.
|
||||||
|
*/
|
||||||
|
public static IntMap synchronizedIntMap(IntMap m) {
|
||||||
|
return new SynchronizedIntMap(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Horked from the Java util class and extended for <code>IntMap</code>.
|
||||||
|
*/
|
||||||
|
protected static class SynchronizedIntMap implements IntMap
|
||||||
|
{
|
||||||
|
private IntMap m; // Backing Map
|
||||||
|
private Object mutex; // Object on which to synchronize
|
||||||
|
|
||||||
|
SynchronizedIntMap(IntMap m) {
|
||||||
|
if (m == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
this.m = m;
|
||||||
|
mutex = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SynchronizedIntMap(IntMap m, Object mutex) {
|
||||||
|
this.m = m;
|
||||||
|
this.mutex = mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
synchronized(mutex) {return m.size();}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty(){
|
||||||
|
synchronized(mutex) {return m.isEmpty();}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKey(int key) {
|
||||||
|
synchronized(mutex) {return m.containsKey(key);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
synchronized(mutex) {return m.containsKey(key);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsValue(Object value){
|
||||||
|
synchronized(mutex) {return m.containsValue(value);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object get(int key) {
|
||||||
|
synchronized(mutex) {return m.get(key);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object get(Object key) {
|
||||||
|
synchronized(mutex) {return m.get(key);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object put(int key, Object value) {
|
||||||
|
synchronized(mutex) {return m.put(key, value);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object put(Object key, Object value) {
|
||||||
|
synchronized(mutex) {return m.put(key, value);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object remove(int key) {
|
||||||
|
synchronized(mutex) {return m.remove(key);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object remove(Object key) {
|
||||||
|
synchronized(mutex) {return m.remove(key);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putAll(Map map) {
|
||||||
|
synchronized(mutex) {m.putAll(map);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
synchronized(mutex) {m.clear();}
|
||||||
|
}
|
||||||
|
|
||||||
|
private transient Set keySet = null;
|
||||||
|
private transient Set entrySet = null;
|
||||||
|
private transient Collection values = null;
|
||||||
|
|
||||||
|
public Set keySet() {
|
||||||
|
synchronized(mutex) {
|
||||||
|
if (keySet==null)
|
||||||
|
keySet = new SynchronizedSet(m.keySet(), mutex);
|
||||||
|
return keySet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set entrySet() {
|
||||||
|
synchronized(mutex) {
|
||||||
|
if (entrySet==null)
|
||||||
|
entrySet = new SynchronizedSet(m.entrySet(), mutex);
|
||||||
|
return entrySet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection values() {
|
||||||
|
synchronized(mutex) {
|
||||||
|
if (values==null)
|
||||||
|
values = new SynchronizedCollection(m.values(), mutex);
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
synchronized(mutex) {return m.equals(o);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
synchronized(mutex) {return m.hashCode();}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
synchronized(mutex) {return m.toString();}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* I wish I could use this from the <code>java.util.Collections</code>
|
||||||
|
* class, but those crazy kids at Sun are always using private and
|
||||||
|
* default access and pointlessly preventing people from properly
|
||||||
|
* reusing their code. Yay!
|
||||||
|
*/
|
||||||
|
protected static class SynchronizedSet
|
||||||
|
extends SynchronizedCollection implements Set {
|
||||||
|
SynchronizedSet(Set s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
SynchronizedSet(Set s, Object mutex) {
|
||||||
|
super(s, mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
synchronized(mutex) {return c.equals(o);}
|
||||||
|
}
|
||||||
|
public int hashCode() {
|
||||||
|
synchronized(mutex) {return c.hashCode();}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* I wish I could use this from the <code>java.util.Collections</code>
|
||||||
|
* class, but those crazy kids at Sun are always using private and
|
||||||
|
* default access and pointlessly preventing people from properly
|
||||||
|
* reusing their code. Yay!
|
||||||
|
*/
|
||||||
|
protected static class SynchronizedCollection
|
||||||
|
implements Collection {
|
||||||
|
Collection c; // Backing Collection
|
||||||
|
Object mutex; // Object on which to synchronize
|
||||||
|
|
||||||
|
SynchronizedCollection(Collection c) {
|
||||||
|
if (c==null)
|
||||||
|
throw new NullPointerException();
|
||||||
|
this.c = c;
|
||||||
|
mutex = this;
|
||||||
|
}
|
||||||
|
SynchronizedCollection(Collection c, Object mutex) {
|
||||||
|
this.c = c;
|
||||||
|
this.mutex = mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
synchronized(mutex) {return c.size();}
|
||||||
|
}
|
||||||
|
public boolean isEmpty() {
|
||||||
|
synchronized(mutex) {return c.isEmpty();}
|
||||||
|
}
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
synchronized(mutex) {return c.contains(o);}
|
||||||
|
}
|
||||||
|
public Object[] toArray() {
|
||||||
|
synchronized(mutex) {return c.toArray();}
|
||||||
|
}
|
||||||
|
public Object[] toArray(Object[] a) {
|
||||||
|
synchronized(mutex) {return c.toArray(a);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator iterator() {
|
||||||
|
return c.iterator(); // Must be manually synched by user!
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(Object o) {
|
||||||
|
synchronized(mutex) {return c.add(o);}
|
||||||
|
}
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
synchronized(mutex) {return c.remove(o);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsAll(Collection coll) {
|
||||||
|
synchronized(mutex) {return c.containsAll(coll);}
|
||||||
|
}
|
||||||
|
public boolean addAll(Collection coll) {
|
||||||
|
synchronized(mutex) {return c.addAll(coll);}
|
||||||
|
}
|
||||||
|
public boolean removeAll(Collection coll) {
|
||||||
|
synchronized(mutex) {return c.removeAll(coll);}
|
||||||
|
}
|
||||||
|
public boolean retainAll(Collection coll) {
|
||||||
|
synchronized(mutex) {return c.retainAll(coll);}
|
||||||
|
}
|
||||||
|
public void clear() {
|
||||||
|
synchronized(mutex) {c.clear();}
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
synchronized(mutex) {return c.toString();}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: HashIntMap.java,v 1.3 2001/08/11 22:43:29 mdb Exp $
|
// $Id: HashIntMap.java,v 1.4 2001/09/15 17:22:11 mdb Exp $
|
||||||
//
|
//
|
||||||
// samskivert library - useful routines for java programs
|
// samskivert library - useful routines for java programs
|
||||||
// Copyright (C) 2001 Michael Bayne
|
// Copyright (C) 2001 Michael Bayne
|
||||||
@@ -20,63 +20,81 @@
|
|||||||
|
|
||||||
package com.samskivert.util;
|
package com.samskivert.util;
|
||||||
|
|
||||||
import java.util.Enumeration;
|
import java.util.*;
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An int map is like a hashmap, but with integers as keys. We avoid the
|
* An int map is like a regular map, but with integers as keys. We avoid
|
||||||
* annoyance of having to create integer objects every time we want to
|
* the annoyance of having to create integer objects every time we want to
|
||||||
* lookup or insert values.
|
* lookup or insert values. The hash int map is an int map that uses a
|
||||||
|
* hashtable mechanism to store its key/value mappings.
|
||||||
*/
|
*/
|
||||||
public class IntMap
|
public class HashIntMap
|
||||||
|
extends AbstractMap implements IntMap
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The default number of buckets to use for the hash table.
|
||||||
|
*/
|
||||||
public final static int DEFAULT_BUCKETS = 64;
|
public final static int DEFAULT_BUCKETS = 64;
|
||||||
|
|
||||||
public IntMap (int buckets)
|
/**
|
||||||
|
* Constructs an empty hash int map with the specified number of hash
|
||||||
|
* buckets.
|
||||||
|
*/
|
||||||
|
public HashIntMap (int buckets)
|
||||||
{
|
{
|
||||||
_buckets = new Record[buckets];
|
_buckets = new Record[buckets];
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntMap ()
|
/**
|
||||||
|
* Constructs an empty hash int map with the default number of hash
|
||||||
|
* buckets.
|
||||||
|
*/
|
||||||
|
public HashIntMap ()
|
||||||
{
|
{
|
||||||
this(DEFAULT_BUCKETS);
|
this(DEFAULT_BUCKETS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int size ()
|
// documentation inherited
|
||||||
|
public int size ()
|
||||||
{
|
{
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void put (int key, Object value)
|
// documentation inherited
|
||||||
|
public boolean containsKey (Object key)
|
||||||
{
|
{
|
||||||
int index = Math.abs(key)%_buckets.length;
|
return containsKey(((Integer)key).intValue());
|
||||||
Record rec = _buckets[index];
|
|
||||||
|
|
||||||
// either we start a new chain
|
|
||||||
if (rec == null) {
|
|
||||||
_buckets[index] = new Record(key, value);
|
|
||||||
_size++; // we're bigger
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// or we replace an element in an existing chain
|
|
||||||
Record prev = rec;
|
|
||||||
for (; rec != null; rec = rec.next) {
|
|
||||||
if (rec.key == key) {
|
|
||||||
rec.value = value; // we're not bigger
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
prev = rec;
|
|
||||||
}
|
|
||||||
|
|
||||||
// or we append it to this chain
|
|
||||||
prev.next = new Record(key, value);
|
|
||||||
_size++; // we're bigger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Object get (int key)
|
// documentation inherited
|
||||||
|
public boolean containsKey (int key)
|
||||||
{
|
{
|
||||||
int index = Math.abs(key)%_buckets.length;
|
return get(key) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public boolean containsValue (Object o)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _buckets.length; i++) {
|
||||||
|
for (Record r = _buckets[i]; r != null; r = r.next) {
|
||||||
|
if (r.value.equals(o)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public Object get (Object key)
|
||||||
|
{
|
||||||
|
return get(((Integer)key).intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public Object get (int key)
|
||||||
|
{
|
||||||
|
int index = Math.abs(key) % _buckets.length;
|
||||||
for (Record rec = _buckets[index]; rec != null; rec = rec.next) {
|
for (Record rec = _buckets[index]; rec != null; rec = rec.next) {
|
||||||
if (rec.key == key) {
|
if (rec.key == key) {
|
||||||
return rec.value;
|
return rec.value;
|
||||||
@@ -85,16 +103,59 @@ public class IntMap
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains (int key)
|
// documentation inherited
|
||||||
|
public Object put (Object key, Object value)
|
||||||
{
|
{
|
||||||
return get(key) != null;
|
return put(((Integer)key).intValue(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Object remove (int key)
|
// documentation inherited
|
||||||
|
public Object put (int key, Object value)
|
||||||
{
|
{
|
||||||
|
// disallow null values
|
||||||
|
if (value == null) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
int index = Math.abs(key)%_buckets.length;
|
int index = Math.abs(key)%_buckets.length;
|
||||||
Record rec = _buckets[index];
|
Record rec = _buckets[index];
|
||||||
|
|
||||||
|
// either we start a new chain
|
||||||
|
if (rec == null) {
|
||||||
|
_buckets[index] = new Record(key, value);
|
||||||
|
_size++; // we're bigger
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// or we replace an element in an existing chain
|
||||||
|
Record prev = rec;
|
||||||
|
for (; rec != null; rec = rec.next) {
|
||||||
|
if (rec.key == key) {
|
||||||
|
Object ovalue = rec.value;
|
||||||
|
rec.value = value; // we're not bigger
|
||||||
|
return ovalue;
|
||||||
|
}
|
||||||
|
prev = rec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// or we append it to this chain
|
||||||
|
prev.next = new Record(key, value);
|
||||||
|
_size++; // we're bigger
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public Object remove (Object key)
|
||||||
|
{
|
||||||
|
return remove(((Integer)key).intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public Object remove (int key)
|
||||||
|
{
|
||||||
|
int index = Math.abs(key) % _buckets.length;
|
||||||
|
Record rec = _buckets[index];
|
||||||
|
|
||||||
// if there's no chain, there's no object
|
// if there's no chain, there's no object
|
||||||
if (rec == null) {
|
if (rec == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -120,7 +181,8 @@ public class IntMap
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void clear ()
|
// documentation inherited
|
||||||
|
public void clear ()
|
||||||
{
|
{
|
||||||
// abandon all of our hash chains (the joy of garbage collection)
|
// abandon all of our hash chains (the joy of garbage collection)
|
||||||
for (int i = 0; i < _buckets.length; i++) {
|
for (int i = 0; i < _buckets.length; i++) {
|
||||||
@@ -130,17 +192,99 @@ public class IntMap
|
|||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Enumeration keys ()
|
// documentation inherited
|
||||||
|
public Set entrySet ()
|
||||||
{
|
{
|
||||||
return new Enumerator(_buckets, true);
|
return new AbstractSet() {
|
||||||
|
public int size ()
|
||||||
|
{
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator iterator ()
|
||||||
|
{
|
||||||
|
return new EntryIterator();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Enumeration elements ()
|
protected class EntryIterator implements Iterator
|
||||||
{
|
{
|
||||||
return new Enumerator(_buckets, false);
|
public boolean hasNext ()
|
||||||
|
{
|
||||||
|
// if we're pointing to an entry, we've got more entries
|
||||||
|
if (_record != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search backward through the buckets looking for the next
|
||||||
|
// non-empty hash chain
|
||||||
|
while (_index-- > 0) {
|
||||||
|
if ((_record = _buckets[_index]) != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// found no non-empty hash chains, we're done
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object next ()
|
||||||
|
{
|
||||||
|
// if we're not pointing to an entry, search for the next
|
||||||
|
// non-empty hash chain
|
||||||
|
if (_record == null) {
|
||||||
|
while ((_index-- > 0) &&
|
||||||
|
((_record = _buckets[_index]) == null));
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep track of the last thing we returned
|
||||||
|
_last = _record;
|
||||||
|
|
||||||
|
// if we found a record, return it's value and move our record
|
||||||
|
// reference to it's successor
|
||||||
|
if (_record != null) {
|
||||||
|
_record = _last.next;
|
||||||
|
return _last;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove ()
|
||||||
|
{
|
||||||
|
if (_last == null) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the record the hard way
|
||||||
|
HashIntMap.this.remove(_last.key);
|
||||||
|
_last = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int _index = _buckets.length;
|
||||||
|
protected Record _record, _last;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class Record
|
/**
|
||||||
|
* Returns an iteration over the keys of this hash int map. The keys
|
||||||
|
* are returned as <code>Integer</code> objects.
|
||||||
|
*/
|
||||||
|
public Iterator keys ()
|
||||||
|
{
|
||||||
|
return keySet().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iteration over the elements (values) of this hash int
|
||||||
|
* map.
|
||||||
|
*/
|
||||||
|
public Iterator elements ()
|
||||||
|
{
|
||||||
|
return values().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class Record implements Entry
|
||||||
{
|
{
|
||||||
public Record next;
|
public Record next;
|
||||||
public int key;
|
public int key;
|
||||||
@@ -151,86 +295,74 @@ public class IntMap
|
|||||||
this.key = key;
|
this.key = key;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object getKey ()
|
||||||
|
{
|
||||||
|
return new Integer(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValue ()
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object setValue (Object value)
|
||||||
|
{
|
||||||
|
Object ovalue = this.value;
|
||||||
|
this.value = value;
|
||||||
|
return ovalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals (Object o)
|
||||||
|
{
|
||||||
|
if (o instanceof Record) {
|
||||||
|
Record or = (Record)o;
|
||||||
|
return (key == or.key) && value.equals(or.value);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode ()
|
||||||
|
{
|
||||||
|
return key ^ ((value == null) ? 0 : value.hashCode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Enumerator implements Enumeration
|
public static void main (String[] args)
|
||||||
{
|
{
|
||||||
public Enumerator (Record[] buckets, boolean returnKeys)
|
HashIntMap table = new HashIntMap();
|
||||||
{
|
|
||||||
_buckets = buckets;
|
|
||||||
_index = buckets.length;
|
|
||||||
_returnKeys = returnKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasMoreElements ()
|
System.out.print("Inserting: ");
|
||||||
{
|
for (int i = 10; i < 100; i++) {
|
||||||
// if we're pointing to an entry, we've got more entries
|
Integer value = new Integer(i);
|
||||||
if (_record != null) {
|
table.put(i, value);
|
||||||
return true;
|
System.out.print("(" + i + "," + value + ")");
|
||||||
}
|
}
|
||||||
|
System.out.println("");
|
||||||
|
|
||||||
// search backward through the buckets looking for the next
|
System.out.print("Looking up: ");
|
||||||
// non-empty hash chain
|
for (int i = 10; i < 100; i++) {
|
||||||
while (_index-- > 0) {
|
System.out.print("(" + i + "," + table.get(i) + ")");
|
||||||
if ((_record = _buckets[_index]) != null) {
|
}
|
||||||
return true;
|
System.out.println("");
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// found no non-empty hash chains, we're done
|
System.out.println("Keys: " +
|
||||||
return false;
|
StringUtil.toString(table.keys()));
|
||||||
}
|
System.out.println("Elems: " +
|
||||||
|
StringUtil.toString(table.elements()));
|
||||||
|
|
||||||
public Object nextElement ()
|
System.out.print("Removing: ");
|
||||||
{
|
for (int i = 10; i < 98; i++) {
|
||||||
// if we're not pointing to an entry, search for the next
|
System.out.print("(" + i + "," + table.remove(i) + ")");
|
||||||
// non-empty hash chain
|
}
|
||||||
if (_record == null) {
|
System.out.println("");
|
||||||
while ((_index-- > 0) &&
|
|
||||||
((_record = _buckets[_index]) == null));
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we found a record, return it's value and move our record
|
System.out.println("Keys: " +
|
||||||
// reference to it's successor
|
StringUtil.toString(table.keys()));
|
||||||
if (_record != null) {
|
System.out.println("Elems: " +
|
||||||
Record r = _record;
|
StringUtil.toString(table.elements()));
|
||||||
_record = r.next;
|
}
|
||||||
return _returnKeys ? new Integer(r.key) : r.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new NoSuchElementException("IntMapEnumerator");
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _index;
|
|
||||||
private Record _record;
|
|
||||||
private Record[] _buckets;
|
|
||||||
private boolean _returnKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public static void main (String[] args)
|
|
||||||
// {
|
|
||||||
// IntMap table = new IntMap();
|
|
||||||
|
|
||||||
// System.out.print("Inserting: ");
|
|
||||||
// for (int i = 10; i < 100; i++) {
|
|
||||||
// Integer value = new Integer(i);
|
|
||||||
// table.put(i, value);
|
|
||||||
// System.out.print("(" + i + "," + value + ")");
|
|
||||||
// }
|
|
||||||
// System.out.println("");
|
|
||||||
|
|
||||||
// System.out.print("Looking up: ");
|
|
||||||
// for (int i = 10; i < 100; i++) {
|
|
||||||
// System.out.print("(" + i + "," + table.get(i) + ")");
|
|
||||||
// }
|
|
||||||
// System.out.println("");
|
|
||||||
|
|
||||||
// System.out.print("Removing: ");
|
|
||||||
// for (int i = 10; i < 100; i++) {
|
|
||||||
// System.out.print("(" + i + "," + table.remove(i) + ")");
|
|
||||||
// }
|
|
||||||
// System.out.println("");
|
|
||||||
// }
|
|
||||||
|
|
||||||
private Record[] _buckets;
|
private Record[] _buckets;
|
||||||
private int _size;
|
private int _size;
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
//
|
||||||
|
// $Id: IntMap.java,v 1.1 2001/09/15 17:22:11 mdb Exp $
|
||||||
|
//
|
||||||
|
// samskivert library - useful routines for java programs
|
||||||
|
// Copyright (C) 2001 Michael Bayne
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.samskivert.util;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An int map is a map that uses integers as keys and provides accessors
|
||||||
|
* that eliminate the need to create and manipulate superfluous
|
||||||
|
* <code>Integer</code> objects. It extends the <code>Map</code> interface
|
||||||
|
* and therefore provides all of the standard accessors (for which
|
||||||
|
* <code>Integer</code> objects should be supplied as keys).
|
||||||
|
*/
|
||||||
|
public interface IntMap extends Map
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns <tt>true</tt> if this map contains a mapping for the
|
||||||
|
* specified key.
|
||||||
|
*
|
||||||
|
* @param key key whose presence in this map is to be tested.
|
||||||
|
*
|
||||||
|
* @return <tt>true</tt> if this map contains a mapping for the
|
||||||
|
* specified key.
|
||||||
|
*/
|
||||||
|
public boolean containsKey (int key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to which this map maps the specified key. Returns
|
||||||
|
* <tt>null</tt> if the map contains no mapping for this key.
|
||||||
|
*
|
||||||
|
* @param key key whose associated value is to be returned.
|
||||||
|
*
|
||||||
|
* @return the value to which this map maps the specified key, or
|
||||||
|
* <tt>null</tt> if the map contains no mapping for this key.
|
||||||
|
*/
|
||||||
|
public Object get (int key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associates the specified value with the specified key in this map.
|
||||||
|
* If the map previously contained a mapping for this key, the old
|
||||||
|
* value is replaced.
|
||||||
|
*
|
||||||
|
* @param key key with which the specified value is to be associated.
|
||||||
|
* @param value value to be associated with the specified key.
|
||||||
|
*
|
||||||
|
* @return previous value associated with specified key, or
|
||||||
|
* <tt>null</tt> if there was no mapping for key.
|
||||||
|
*/
|
||||||
|
public Object put (int key, Object value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the mapping for this key from this map if present.
|
||||||
|
*
|
||||||
|
* @param key key whose mapping is to be removed from the map.
|
||||||
|
*
|
||||||
|
* @return previous value associated with specified key, or
|
||||||
|
* <tt>null</tt> if there was no mapping for key.
|
||||||
|
*/
|
||||||
|
public Object remove (int key);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: IntervalManager.java,v 1.3 2001/08/11 22:43:29 mdb Exp $
|
// $Id: IntervalManager.java,v 1.4 2001/09/15 17:22:11 mdb Exp $
|
||||||
//
|
//
|
||||||
// samskivert library - useful routines for java programs
|
// samskivert library - useful routines for java programs
|
||||||
// Copyright (C) 2001 Michael Bayne
|
// Copyright (C) 2001 Michael Bayne
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
package com.samskivert.util;
|
package com.samskivert.util;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.Collections;
|
||||||
import com.samskivert.Log;
|
import com.samskivert.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -245,7 +246,7 @@ public class IntervalManager extends Thread
|
|||||||
// to rewrite this such that we can add and remove intervaleds much
|
// to rewrite this such that we can add and remove intervaleds much
|
||||||
// faster.
|
// faster.
|
||||||
protected static ArrayList _schedule = new ArrayList();
|
protected static ArrayList _schedule = new ArrayList();
|
||||||
protected static IntMap _hash = new IntMap();
|
protected static HashIntMap _hash = new HashIntMap();
|
||||||
protected static long _nextwake = Long.MAX_VALUE;
|
protected static long _nextwake = Long.MAX_VALUE;
|
||||||
|
|
||||||
protected static int _helpers = 0; // # of created helpers
|
protected static int _helpers = 0; // # of created helpers
|
||||||
|
|||||||
Reference in New Issue
Block a user