Author: manik.surtani(a)jboss.com
Date: 2009-02-19 07:03:50 -0500 (Thu, 19 Feb 2009)
New Revision: 7727
Modified:
core/branches/flat/src/main/java/org/horizon/container/UnsortedDataContainer.java
core/branches/flat/src/main/java/org/horizon/util/AbstractMap.java
core/branches/flat/src/main/java/org/horizon/util/BidirectionalLinkedHashMap.java
core/branches/flat/src/main/java/org/horizon/util/FastCopyHashMap.java
Log:
Removed support for null keys
Modified:
core/branches/flat/src/main/java/org/horizon/container/UnsortedDataContainer.java
===================================================================
---
core/branches/flat/src/main/java/org/horizon/container/UnsortedDataContainer.java 2009-02-18
17:40:47 UTC (rev 7726)
+++
core/branches/flat/src/main/java/org/horizon/container/UnsortedDataContainer.java 2009-02-19
12:03:50 UTC (rev 7727)
@@ -50,7 +50,6 @@
// stuff, we don't need to iterate through immortal data.
final ConcurrentMap<Object, CachedValue> immortalData = new
ConcurrentHashMap<Object, CachedValue>();
final ConcurrentMap<Object, ExpirableCachedValue> expirableData = new
ConcurrentHashMap<Object, ExpirableCachedValue>();
- private static final Object NULL = new Object();
private CacheLoaderManager clm;
private CacheStore cacheStore;
@@ -75,25 +74,16 @@
}
}
- private Object maskNullKey(Object o) {
- return o == null ? NULL : o;
- }
-
- private Object unmaskNullKey(Object o) {
- return (o == NULL) ? null : o;
- }
-
public Object get(Object k) {
- Object maskedKey = maskNullKey(k);
- CachedValue cv = immortalData.get(maskedKey);
+ CachedValue cv = immortalData.get(k);
if (cv != null) {
cv.touch();
return cv.getValue();
} else {
- ExpirableCachedValue ecv = expirableData.get(maskedKey);
+ ExpirableCachedValue ecv = expirableData.get(k);
if (ecv != null) {
if (ecv.isExpired()) {
- expire(maskedKey);
+ expire(k);
} else {
ecv.touch();
return ecv.getValue();
@@ -105,9 +95,7 @@
}
public void put(Object k, Object v, long lifespan) {
- Object maskedKey = maskNullKey(k);
-
- CachedValue cv = immortalData.get(maskedKey);
+ CachedValue cv = immortalData.get(k);
ExpirableCachedValue ecv;
if (cv != null) {
// do we need to move this to expirable?
@@ -117,16 +105,16 @@
cv.touch();
} else {
ecv = new ExpirableCachedValue(v, lifespan);
- immortalData.remove(maskedKey);
- expirableData.put(maskedKey, ecv);
+ immortalData.remove(k);
+ expirableData.put(k, ecv);
}
- } else if ((ecv = expirableData.get(maskedKey)) != null) {
+ } else if ((ecv = expirableData.get(k)) != null) {
// do we need to move this to immortal?
if (lifespan < 0) {
// yes.
cv = new CachedValue(v);
- expirableData.remove(maskedKey);
- immortalData.put(maskedKey, cv);
+ expirableData.remove(k);
+ immortalData.put(k, cv);
} else {
ecv.setValue(v);
ecv.touch();
@@ -135,21 +123,20 @@
// does not exist anywhere!
if (lifespan < 0) {
cv = new CachedValue(v);
- immortalData.put(maskedKey, cv);
+ immortalData.put(k, cv);
} else {
ecv = new ExpirableCachedValue(v, lifespan);
- expirableData.put(maskedKey, ecv);
+ expirableData.put(k, ecv);
}
}
}
public boolean containsKey(Object k) {
- Object maskedKey = maskNullKey(k);
- if (!immortalData.containsKey(maskedKey)) {
- ExpirableCachedValue ecv = expirableData.get(maskedKey);
+ if (!immortalData.containsKey(k)) {
+ ExpirableCachedValue ecv = expirableData.get(k);
if (ecv == null) return false;
if (ecv.isExpired()) {
- expire(maskedKey);
+ expire(k);
return false;
}
}
@@ -157,16 +144,14 @@
}
public long getModifiedTimestamp(Object key) {
- Object maskedKey = maskNullKey(key);
- CachedValue cv = immortalData.get(maskedKey);
- if (cv == null) cv = expirableData.get(maskedKey);
+ CachedValue cv = immortalData.get(key);
+ if (cv == null) cv = expirableData.get(key);
return cv == null ? -1 : cv.getModifiedTime();
}
public Object remove(Object k) {
- Object maskedKey = maskNullKey(k);
- CachedValue cv = immortalData.remove(maskedKey);
- if (cv == null) cv = expirableData.remove(maskedKey);
+ CachedValue cv = immortalData.remove(k);
+ if (cv == null) cv = expirableData.remove(k);
if (cv == null) {
return null;
@@ -238,8 +223,7 @@
}
public boolean contains(Object o) {
- Object maskedKey = maskNullKey((Object) o);
- return immortalKeys.contains(maskedKey) || expirableKeys.contains(maskedKey);
+ return immortalKeys.contains(o) || expirableKeys.contains(o);
}
public boolean remove(Object o) {
@@ -277,7 +261,7 @@
@SuppressWarnings("unchecked")
public Object next() {
- return unmaskNullKey(currentIterator.next());
+ return currentIterator.next();
}
public void remove() {
Modified: core/branches/flat/src/main/java/org/horizon/util/AbstractMap.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/util/AbstractMap.java 2009-02-18 17:40:47
UTC (rev 7726)
+++ core/branches/flat/src/main/java/org/horizon/util/AbstractMap.java 2009-02-19 12:03:50
UTC (rev 7727)
@@ -5,18 +5,13 @@
import java.util.Set;
/**
- * Similar to the JDK's AbstractMap, this provides common functionality for custom
map implementations.
+ * Similar to the JDK's AbstractMap, this provides common functionality for custom
map implementations. Unlike JDK's
+ * AbstractMap, there is no support for null keys.
*
* @author Manik Surtani
* @since 1.0
*/
public abstract class AbstractMap<K, V> implements Map<K, V> {
-
- /**
- * Marks null keys.
- */
- private static final Object NULL = new Object();
-
// views
protected transient Set<Map.Entry<K, V>> entrySet = null;
protected transient Set<K> keySet = null;
@@ -30,19 +25,13 @@
return h ^ (h >>> 7) ^ (h >>> 4);
}
- @SuppressWarnings("unchecked")
- protected static final <K> K maskNull(K key) {
- return key == null ? (K) NULL : key;
- }
-
- protected static final <K> K unmaskNull(K key) {
- return key == NULL ? null : key;
- }
-
protected static final boolean eq(Object o1, Object o2) {
return o1 == o2 || (o1 != null && o1.equals(o2));
}
+ protected final void assertKeyNotNull(Object key) {
+ if (key == null) throw new NullPointerException("Null keys are not
supported!");
+ }
protected static class SimpleEntry<K, V> implements Map.Entry<K, V> {
private K key;
Modified:
core/branches/flat/src/main/java/org/horizon/util/BidirectionalLinkedHashMap.java
===================================================================
---
core/branches/flat/src/main/java/org/horizon/util/BidirectionalLinkedHashMap.java 2009-02-18
17:40:47 UTC (rev 7726)
+++
core/branches/flat/src/main/java/org/horizon/util/BidirectionalLinkedHashMap.java 2009-02-19
12:03:50 UTC (rev 7727)
@@ -9,9 +9,18 @@
import java.util.NoSuchElementException;
/**
- * // TODO javadocs
+ * Similar to the JDK's {@link java.util.LinkedHashMap} except that this version
makes use of the fact that entries are
+ * bidirectionally linked and can hence be nagigated either from the start
<i>or</i> from the end. It exposes such
+ * navigability by overriding {@link java.util.Map#keySet()} and {@link
java.util.Map#entrySet()} to return {@link
+ * org.horizon.util.ReversibleSet} rather than a standard JDK {@link java.util.Set}.
{@link
+ * org.horizon.util.ReversibleSet}s allow you to access 2 iterators: one that iterates
from start to end, as usual, and
+ * a reversed one that iterates from end to start instead.
+ * <p/>
+ * Unline the JDK {@link java.util.LinkedHashMap}, this implementation does not support
null keys.
+ * <p/>
*
* @author Manik Surtani
+ * @since 1.0
*/
public class BidirectionalLinkedHashMap<K, V> extends AbstractMap<K, V> {
@@ -221,8 +230,7 @@
* with <tt>key</tt>.)
*/
public V put(K key, V value) {
- if (key == null)
- return putForNullKey(value);
+ assertKeyNotNull(key);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (LinkedEntry<K, V> e = table[i]; e != null; e = e.next) {
@@ -241,23 +249,6 @@
}
/**
- * Offloaded version of put for null keys
- */
- private V putForNullKey(V value) {
- for (LinkedEntry<K, V> e = table[0]; e != null; e = e.next) {
- if (e.key == null) {
- V oldValue = e.value;
- e.value = value;
- e.recordAccess(this);
- return oldValue;
- }
- }
- modCount++;
- addEntry(0, null, value, 0);
- return null;
- }
-
- /**
* This method is used instead of put by constructors and pseudoconstructors (clone,
readObject). It does not resize
* the table, check for comodification, etc. It calls createEntry rather than
addEntry.
*/
@@ -360,6 +351,7 @@
* with <tt>key</tt>.)
*/
public V remove(Object key) {
+ assertKeyNotNull(key);
LinkedEntry<K, V> e = removeEntryForKey(key);
return (e == null ? null : e.value);
}
@@ -369,7 +361,7 @@
* contains no mapping for this key.
*/
final LinkedEntry<K, V> removeEntryForKey(Object key) {
- int hash = (key == null) ? 0 : hash(key.hashCode());
+ int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
LinkedEntry<K, V> prev = table[i];
LinkedEntry<K, V> e = prev;
@@ -598,6 +590,7 @@
* operation may be used to distinguish these two cases.
*/
public V get(Object key) {
+ assertKeyNotNull(key);
LinkedEntry<K, V> e = getEntry(key);
if (e == null)
return null;
Modified: core/branches/flat/src/main/java/org/horizon/util/FastCopyHashMap.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/util/FastCopyHashMap.java 2009-02-18
17:40:47 UTC (rev 7726)
+++ core/branches/flat/src/main/java/org/horizon/util/FastCopyHashMap.java 2009-02-19
12:03:50 UTC (rev 7727)
@@ -34,6 +34,8 @@
/**
* A HashMap that is optimized for fast shallow copies.
+ * <p/>
+ * Null keys are <i>not</i> supported.
*
* @author Jason T. Greene
* @since 1.0
@@ -149,8 +151,7 @@
}
public V get(Object key) {
- key = maskNull(key);
-
+ assertKeyNotNull(key);
int hash = hash(key);
int length = table.length;
int index = index(hash, length);
@@ -168,8 +169,7 @@
}
public boolean containsKey(Object key) {
- key = maskNull(key);
-
+ assertKeyNotNull(key);
int hash = hash(key);
int length = table.length;
int index = index(hash, length);
@@ -195,8 +195,7 @@
}
public V put(K key, V value) {
- key = maskNull(key);
-
+ assertKeyNotNull(key);
Entry<K, V>[] table = this.table;
int hash = hash(key);
int length = table.length;
@@ -274,8 +273,7 @@
}
public V remove(Object key) {
- key = maskNull(key);
-
+ assertKeyNotNull(key);
Entry<K, V>[] table = this.table;
int length = table.length;
int hash = hash(key);
@@ -398,8 +396,6 @@
@SuppressWarnings("unchecked")
private void putForCreate(K key, V value) {
- key = maskNull(key);
-
Entry<K, V>[] table = this.table;
int hash = hash(key);
int length = table.length;
@@ -420,7 +416,7 @@
for (Entry<K, V> e : table) {
if (e != null) {
- s.writeObject(unmaskNull(e.key));
+ s.writeObject(e.key);
s.writeObject(e.value);
}
}
@@ -527,7 +523,7 @@
private class KeyIterator extends FasyCopyHashMapIterator<K> {
public K next() {
- return unmaskNull(nextEntry().key);
+ return nextEntry().key;
}
}
@@ -553,7 +549,7 @@
public Map.Entry<K, V> next() {
Entry<K, V> e = nextEntry();
- return new WriteThroughEntry(unmaskNull(e.key), e.value);
+ return new WriteThroughEntry(e.key, e.value);
}
}