Author: jason.greene(a)jboss.com
Date: 2008-07-30 19:46:45 -0400 (Wed, 30 Jul 2008)
New Revision: 6450
Modified:
core/trunk/src/main/java/org/jboss/cache/util/FastCopyHashMap.java
Log:
Fix null handling for iterators/views
Add optimized copy constructor
Modified: core/trunk/src/main/java/org/jboss/cache/util/FastCopyHashMap.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/FastCopyHashMap.java 2008-07-30 22:58:03
UTC (rev 6449)
+++ core/trunk/src/main/java/org/jboss/cache/util/FastCopyHashMap.java 2008-07-30 23:46:45
UTC (rev 6450)
@@ -40,8 +40,14 @@
*/
public class FastCopyHashMap<K, V> extends AbstractMap<K, V> implements
Map<K, V>, Cloneable, Serializable
{
+ /**
+ * Marks null keys.
+ */
+ private static final Object NULL = new Object();
- private static final Object NULL = new Object();
+ /**
+ * Serialization ID
+ */
private static final long serialVersionUID = 10929568968762L;
/**
@@ -80,7 +86,7 @@
private final float loadFactor;
/**
- * Counter used to detech changes made outside of an iterator
+ * Counter used to detect changes made outside of an iterator
*/
private transient int modCount;
@@ -104,13 +110,22 @@
init(initialCapacity, loadFactor);
}
- public FastCopyHashMap(Map<K, V> data)
+ public FastCopyHashMap(Map<? extends K, ? extends V> map)
{
- this();
- putAll(data);
+ this(map.size());
+ putAll(map);
}
@SuppressWarnings("unchecked")
+ public FastCopyHashMap(FastCopyHashMap<? extends K, ? extends V> map)
+ {
+ this.table = (Entry<K, V>[])map.table.clone();
+ this.loadFactor = map.loadFactor;
+ this.size = map.size;
+ this.threshold = map.threshold;
+ }
+
+ @SuppressWarnings("unchecked")
private void init(int initialCapacity, float loadFactor)
{
int c = 1;
@@ -139,6 +154,17 @@
return h ^ (h >>> 7) ^ (h >>> 4);
}
+ @SuppressWarnings("unchecked")
+ private static final <K> K maskNull(K key)
+ {
+ return key == null ? (K) NULL : key;
+ }
+
+ private static final <K> K unmaskNull(K key)
+ {
+ return key == NULL ? null : key;
+ }
+
private int nextIndex(int index, int length)
{
index = (index >= length - 1) ? 0 : index + 1;
@@ -167,7 +193,7 @@
public V get(Object key)
{
- if (key == null) key = NULL;
+ key = maskNull(key);
int hash = hash(key);
int length = table.length;
@@ -188,7 +214,7 @@
public boolean containsKey(Object key)
{
- if (key == null) key = NULL;
+ key = maskNull(key);
int hash = hash(key);
int length = table.length;
@@ -216,12 +242,10 @@
return false;
}
- @SuppressWarnings("unchecked")
public V put(K key, V value)
{
- if (key == null) key = (K) NULL;
+ key = maskNull(key);
-
Entry<K, V>[] table = this.table;
int hash = hash(key);
int length = table.length;
@@ -306,7 +330,7 @@
public V remove(Object key)
{
- if (key == null) key = NULL;
+ key = maskNull(key);
Entry<K, V>[] table = this.table;
int length = table.length;
@@ -424,7 +448,6 @@
System.out.println(" Optimal: " + optimal + " (" +
(float) optimal * 100 / total + "%)");
System.out.println(" Average Distnce: " + ((float) totalSkew / (total -
optimal)));
System.out.println(" Max Distance: " + maxSkew);
-
}
public Set<Map.Entry<K, V>> entrySet()
@@ -471,7 +494,7 @@
@SuppressWarnings("unchecked")
private void putForCreate(K key, V value)
{
- if (key == null) key = (K) NULL;
+ key = maskNull(key);
Entry<K, V>[] table = this.table;
int hash = hash(key);
@@ -493,11 +516,11 @@
s.defaultWriteObject();
s.writeInt(size);
- for (Entry e : table)
+ for (Entry<K,V> e : table)
{
if (e != null)
{
- s.writeObject(e.key);
+ s.writeObject(unmaskNull(e.key));
s.writeObject(e.value);
}
}
@@ -631,7 +654,7 @@
{
public K next()
{
- return nextEntry().key;
+ return unmaskNull(nextEntry().key);
}
}
@@ -664,7 +687,7 @@
public Map.Entry<K, V> next()
{
Entry<K, V> e = nextEntry();
- return new WriteThroughEntry(e.key, e.value);
+ return new WriteThroughEntry(unmaskNull(e.key), e.value);
}
}