From: <one...@us...> - 2003-02-16 01:55:10
|
Update of /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/util In directory sc8-pr-cvs1:/tmp/cvs-serv7760/hibernate/util Modified Files: IdentityMap.java Log Message: enable use of JDK IdentityHashMap in 1.4+ Index: IdentityMap.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/src/net/sf/hibernate/util/IdentityMap.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** IdentityMap.java 5 Jan 2003 02:11:25 -0000 1.3 --- IdentityMap.java 16 Feb 2003 01:55:07 -0000 1.4 *************** *** 2,16 **** package net.sf.hibernate.util; - import java.util.HashMap; import java.io.Serializable; ! import java.util.*; /** ! * A hashtable where keys are compared by object identity, ! * rather than equals(). */ public final class IdentityMap implements Map, Serializable { private final Map map = new HashMap(); --- 2,69 ---- package net.sf.hibernate.util; import java.io.Serializable; ! import java.util.ArrayList; ! import java.util.Collection; ! import java.util.HashMap; ! import java.util.HashSet; ! import java.util.Iterator; ! import java.util.List; ! import java.util.Map; ! import java.util.Set; ! ! import net.sf.hibernate.AssertionFailure; /** ! * A <tt>Map</tt> where keys are compared by object identity, ! * rather than <tt>equals()</tt>. */ public final class IdentityMap implements Map, Serializable { + private static final Class identityMapClass; + static { + Class imc; + try { + imc = Class.forName("java.util.IdentityHashMap"); + //throw new ClassNotFoundException(); + } + catch (ClassNotFoundException cnfe) { + imc = IdentityMap.class; + } + identityMapClass=imc; + } + + /** + * Return a new instance of this class, or an instance of JDK <tt>IdentityHashMap</tt>, + * if available. (The JDK implementation is significantly faster.) + * + * @return Map + */ + public static Map instantiate() { + try { + return (Map) identityMapClass.newInstance(); + } + catch (Exception ie) { + throw new AssertionFailure("could not instantiate identity map", ie); + } + } + + /** + * Return the map entries (as instances of <tt>Map.Entry</tt> in a collection that + * is safe from concurrent modification). ie. we may safely add new instances to + * the underlying <tt>Map</tt> during iteration of the <tt>entries()</tt>. + * + * @param map + * @return Collection + */ + public static Collection entries(Map map) { + if (identityMapClass==IdentityMap.class) { + return ( (IdentityMap) map ).entryList(); + } + else { + return new ArrayList( map.entrySet() ); + } + } + private final Map map = new HashMap(); *************** *** 50,73 **** } } ! ! private static IdentityKey popKey(Object key) { ! ! /*synchronized(keyCache) { ! if ( keyCache.isEmpty() ) { ! return new Key(key); ! } ! else { ! Key k = (Key) keyCache.pop(); ! k.key = key; ! return k; ! } ! }*/ ! return new IdentityKey(key); ! } ! ! private static void pushKey(IdentityKey k) { ! //keyCache.push(k); ! } ! public int size() { return map.size(); --- 103,107 ---- } } ! public int size() { return map.size(); *************** *** 79,86 **** public boolean containsKey(Object key) { ! IdentityKey k = popKey(key); ! boolean result = map.containsKey(k); ! pushKey(k); ! return result; } --- 113,118 ---- public boolean containsKey(Object key) { ! IdentityKey k = new IdentityKey(key); ! return map.containsKey(k); } *************** *** 90,108 **** public Object get(Object key) { ! IdentityKey k = popKey(key); ! Object result = map.get(k); ! pushKey(k); ! return result; } public Object put(Object key, Object value) { ! return map.put( popKey(key), value ); } public Object remove(Object key) { ! IdentityKey k = popKey(key); ! Object result = map.remove(k); ! pushKey(k); ! return result; } --- 122,136 ---- public Object get(Object key) { ! IdentityKey k = new IdentityKey(key); ! return map.get(k); } public Object put(Object key, Object value) { ! return map.put( new IdentityKey(key), value ); } public Object remove(Object key) { ! IdentityKey k = new IdentityKey(key); ! return map.remove(k); } *************** *** 116,123 **** public void clear() { - Iterator iter = map.keySet().iterator(); - while ( iter.hasNext() ) { - pushKey ( (IdentityKey) iter.next() ); - } map.clear(); } --- 144,147 ---- *************** *** 133,137 **** public Set entrySet() { ! Set set = new HashSet(); Iterator iter = map.entrySet().iterator(); while ( iter.hasNext() ) { --- 157,161 ---- public Set entrySet() { ! Set set = new HashSet( map.size() ); Iterator iter = map.entrySet().iterator(); while ( iter.hasNext() ) { *************** *** 140,143 **** --- 164,222 ---- } return set; + } + + private List entryList() { + ArrayList list = new ArrayList( map.size() ); + Iterator iter = map.entrySet().iterator(); + while ( iter.hasNext() ) { + Map.Entry me = (Map.Entry) iter.next(); + list.add( new IdentityMapEntry( ( (IdentityKey) me.getKey() ).key, me.getValue() ) ); + } + return list; + } + + /** + * Workaround for a JDK 1.4.1 bug where <tt>IdentityHashMap</tt>s are not + * correctly deserialized. + * + * @param map + * @return Object + */ + public static Object serialize(Map map) { + if (identityMapClass==IdentityMap.class) { + return map; + } + else { + Object[] array = new Object[ map.size() * 2 ]; + Iterator iter = map.entrySet().iterator(); + int i=0; + while ( iter.hasNext() ) { + Map.Entry e = (Map.Entry) iter.next(); + array[i++] = e.getKey(); + array[i++] = e.getValue(); + } + return array; + } + } + + /** + * Workaround for a JDK 1.4.1 bug where <tt>IdentityHashMap</tt>s are not + * correctly deserialized. + * + * @param map + * @return Object + */ + public static Map deserialize(Object o) { + if (identityMapClass==IdentityMap.class) { + return (Map) o; + } + else { + Map map = instantiate(); + Object[] array = (Object[]) o; + for ( int i=0; i<array.length; i+=2 ) { + map.put( array[i], array[i+1] ); + } + return map; + } } } |