1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Converted, with some major refactors required. Not as memory-efficient as before, could use additional refactoring. 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Perhaps use four different types of HashEntry classes for max efficiency: 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// normal HashEntry for HARD,HARD 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// HardRefEntry for HARD,(SOFT|WEAK) 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// RefHardEntry for (SOFT|WEAK),HARD 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// RefRefEntry for (SOFT|WEAK),(SOFT|WEAK) 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2002-2004 The Apache Software Foundation 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Licensed under the Apache License, Version 2.0 (the "License"); 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License. 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * http://www.apache.org/licenses/LICENSE-2.0 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS, 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License. 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smack.util.collections; 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.IOException; 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.ObjectInputStream; 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.ObjectOutputStream; 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.lang.ref.Reference; 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.lang.ref.ReferenceQueue; 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.lang.ref.SoftReference; 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.lang.ref.WeakReference; 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.*; 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * An abstract implementation of a hash-based map that allows the entries to 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * be removed by the garbage collector. 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This class implements all the features necessary for a subclass reference 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * hash-based map. Key-value entries are stored in instances of the 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <code>ReferenceEntry</code> class which can be overridden and replaced. 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The iterators can similarly be replaced, without the need to replace the KeySet, 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * EntrySet and Values view classes. 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Overridable methods are provided to change the default hashing behaviour, and 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to change how entries are added to and removed from the map. Hopefully, all you 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * need for unusual subclasses is here. 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * When you construct an <code>AbstractReferenceMap</code>, you can specify what 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * kind of references are used to store the map's keys and values. 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If non-hard references are used, then the garbage collector can remove 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * mappings if a key or value becomes unreachable, or if the JVM's memory is 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * running low. For information on how the different reference types behave, 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * see {@link Reference}. 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Different types of references can be specified for keys and values. 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The keys can be configured to be weak but the values hard, 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * in which case this class will behave like a 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <a href="http://java.sun.com/j2se/1.4/docs/api/java/util/WeakHashMap.html"> 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <code>WeakHashMap</code></a>. However, you can also specify hard keys and 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * weak values, or any other combination. The default constructor uses 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * hard keys and soft values, providing a memory-sensitive cache. 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This {@link Map} implementation does <i>not</i> allow null elements. 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Attempting to add a null key or value to the map will raise a 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <code>NullPointerException</code>. 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All the available iterators can be reset back to the start by casting to 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <code>ResettableIterator</code> and calling <code>reset()</code>. 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This implementation is not synchronized. 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You can use {@link java.util.Collections#synchronizedMap} to 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * provide synchronized access to a <code>ReferenceMap</code>. 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Paul Jack 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Matt Hall, John Watkinson, Stephen Colebourne 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $ 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see java.lang.ref.Reference 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @since Commons Collections 3.1 (extracted from ReferenceMap in 3.0) 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic abstract class AbstractReferenceMap <K,V> extends AbstractHashedMap<K, V> { 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Constant indicating that hard references should be used 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static final int HARD = 0; 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Constant indicating that soft references should be used 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static final int SOFT = 1; 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Constant indicating that weak references should be used 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static final int WEAK = 2; 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The reference type for keys. Must be HARD, SOFT, WEAK. 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @serial 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected int keyType; 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The reference type for values. Must be HARD, SOFT, WEAK. 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @serial 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected int valueType; 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Should the value be automatically purged when the associated key has been collected? 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected boolean purgeValues; 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * ReferenceQueue used to eliminate stale mappings. 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See purge. 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private transient ReferenceQueue queue; 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Constructor used during deserialization. 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected AbstractReferenceMap() { 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(); 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Constructs a new empty map with the specified reference types, 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * load factor and initial capacity. 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param keyType the type of reference to use for keys; 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * must be {@link #SOFT} or {@link #WEAK} 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param valueType the type of reference to use for values; 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * must be {@link #SOFT} or {@link #WEAK} 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param capacity the initial capacity for the map 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param loadFactor the load factor for the map 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param purgeValues should the value be automatically purged when the 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * key is garbage collected 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected AbstractReferenceMap(int keyType, int valueType, int capacity, float loadFactor, boolean purgeValues) { 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(capacity, loadFactor); 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen verify("keyType", keyType); 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen verify("valueType", valueType); 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.keyType = keyType; 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.valueType = valueType; 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.purgeValues = purgeValues; 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Initialise this subclass during construction, cloning or deserialization. 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void init() { 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen queue = new ReferenceQueue(); 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Checks the type int is a valid value. 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name the name for error messages 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type the type value to check 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IllegalArgumentException if the value if invalid 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static void verify(String name, int type) { 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if ((type < HARD) || (type > WEAK)) { 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException(name + " must be HARD, SOFT, WEAK."); 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the size of the map. 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the size 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public int size() { 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen purgeBeforeRead(); 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return super.size(); 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Checks whether the map is currently empty. 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return true if the map is currently size zero 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean isEmpty() { 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen purgeBeforeRead(); 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return super.isEmpty(); 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Checks whether the map contains the specified key. 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param key the key to search for 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return true if the map contains the key 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean containsKey(Object key) { 200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen purgeBeforeRead(); 201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Entry entry = getEntry(key); 202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (entry == null) { 203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (entry.getValue() != null); 206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Checks whether the map contains the specified value. 210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param value the value to search for 212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return true if the map contains the value 213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean containsValue(Object value) { 215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen purgeBeforeRead(); 216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (value == null) { 217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return super.containsValue(value); 220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the value mapped to the key specified. 224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param key the key 226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the mapped value, null if no match 227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public V get(Object key) { 229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen purgeBeforeRead(); 230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Entry<K, V> entry = getEntry(key); 231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (entry == null) { 232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return entry.getValue(); 235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Puts a key-value mapping into this map. 240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Neither the key nor the value may be null. 241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param key the key to add, must not be null 243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param value the value to add, must not be null 244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the value previously mapped to this key, null if none 245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws NullPointerException if either the key or value is null 246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public V put(K key, V value) { 248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (key == null) { 249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new NullPointerException("null keys not allowed"); 250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (value == null) { 252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new NullPointerException("null values not allowed"); 253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen purgeBeforeWrite(); 256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return super.put(key, value); 257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes the specified mapping from this map. 261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param key the mapping to remove 263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the value mapped to the removed key, null if key not in map 264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public V remove(Object key) { 266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (key == null) { 267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen purgeBeforeWrite(); 270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return super.remove(key); 271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Clears this map. 275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void clear() { 277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super.clear(); 278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (queue.poll() != null) { 279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } // drain the queue 280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets a MapIterator over the reference map. 285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The iterator only returns valid key/value pairs. 286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a map iterator 288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public MapIterator<K, V> mapIterator() { 290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new ReferenceMapIterator<K, V>(this); 291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a set view of this map's entries. 295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * An iterator returned entry is valid until <code>next()</code> is called again. 296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The <code>setValue()</code> method on the <code>toArray</code> entries has no effect. 297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a set view of this map's entries 299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Set<Map.Entry<K, V>> entrySet() { 301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (entrySet == null) { 302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen entrySet = new ReferenceEntrySet<K, V>(this); 303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return entrySet; 305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a set view of this map's keys. 309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a set view of this map's keys 311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Set<K> keySet() { 313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (keySet == null) { 314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen keySet = new ReferenceKeySet<K, V>(this); 315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return keySet; 317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a collection view of this map's values. 321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a set view of this map's values 323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Collection<V> values() { 325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (values == null) { 326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen values = new ReferenceValues<K, V>(this); 327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return values; 329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Purges stale mappings from this map before read operations. 334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This implementation calls {@link #purge()} to maintain a consistent state. 336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void purgeBeforeRead() { 338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen purge(); 339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Purges stale mappings from this map before write operations. 343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This implementation calls {@link #purge()} to maintain a consistent state. 345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void purgeBeforeWrite() { 347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen purge(); 348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Purges stale mappings from this map. 352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Note that this method is not synchronized! Special 354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * care must be taken if, for instance, you want stale 355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * mappings to be removed on a periodic basis by some 356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * background thread. 357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void purge() { 359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Reference ref = queue.poll(); 360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (ref != null) { 361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen purge(ref); 362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ref = queue.poll(); 363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Purges the specified reference. 368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ref the reference to purge 370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void purge(Reference ref) { 372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // The hashCode of the reference is the hashCode of the 373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // mapping key, even if the reference refers to the 374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // mapping value... 375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int hash = ref.hashCode(); 376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int index = hashIndex(hash, data.length); 377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen HashEntry<K, V> previous = null; 378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen HashEntry<K, V> entry = data[index]; 379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (entry != null) { 380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (((ReferenceEntry<K, V>) entry).purge(ref)) { 381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (previous == null) { 382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen data[index] = entry.next; 383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen previous.next = entry.next; 385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.size--; 387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen previous = entry; 390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen entry = entry.next; 391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the entry mapped to the key specified. 398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param key the key 400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the entry, null if no match 401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected HashEntry<K, V> getEntry(Object key) { 403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (key == null) { 404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return super.getEntry(key); 407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the hash code for a MapEntry. 412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Subclasses can override this, for example to use the identityHashCode. 413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param key the key to get a hash code for, may be null 415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param value the value to get a hash code for, may be null 416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the hash code, as per the MapEntry specification 417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected int hashEntry(Object key, Object value) { 419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()); 420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Compares two keys, in internal converted form, to see if they are equal. 424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This implementation converts the key from the entry to a real reference 426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * before comparison. 427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param key1 the first key to compare passed in from outside 429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param key2 the second key extracted from the entry via <code>entry.key</code> 430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return true if equal 431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected boolean isEqualKey(Object key1, Object key2) { 433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //if ((key1 == null) && (key2 != null) || (key1 != null) || (key2 == null)) { 434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // return false; 435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //} 436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // GenericsNote: Conversion from reference handled by getKey() which replaced all .key references 437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //key2 = (keyType > HARD ? ((Reference) key2).get() : key2); 438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (key1 == key2 || key1.equals(key2)); 439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a ReferenceEntry instead of a HashEntry. 443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param next the next entry in sequence 445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param hashCode the hash code to use 446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param key the key to store 447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param value the value to store 448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the newly created entry 449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public HashEntry<K, V> createEntry(HashEntry<K, V> next, int hashCode, K key, V value) { 451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new ReferenceEntry<K, V>(this, (ReferenceEntry<K, V>) next, hashCode, key, value); 452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates an entry set iterator. 456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the entrySet iterator 458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected Iterator<Map.Entry<K, V>> createEntrySetIterator() { 460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new ReferenceEntrySetIterator<K, V>(this); 461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates an key set iterator. 465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the keySet iterator 467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected Iterator<K> createKeySetIterator() { 469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new ReferenceKeySetIterator<K, V>(this); 470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates an values iterator. 474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the values iterator 476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected Iterator<V> createValuesIterator() { 478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new ReferenceValuesIterator<K, V>(this); 479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * EntrySet implementation. 484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen static class ReferenceEntrySet <K,V> extends EntrySet<K, V> { 486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected ReferenceEntrySet(AbstractHashedMap<K, V> parent) { 488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(parent); 489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Object[] toArray() { 492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return toArray(new Object[0]); 493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public <T> T[] toArray(T[] arr) { 496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // special implementation to handle disappearing entries 497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ArrayList<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(); 498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Iterator<Map.Entry<K, V>> iterator = iterator(); 499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (iterator.hasNext()) { 500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Map.Entry<K, V> e = iterator.next(); 501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen list.add(new DefaultMapEntry<K, V>(e.getKey(), e.getValue())); 502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return list.toArray(arr); 504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * KeySet implementation. 510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen static class ReferenceKeySet <K,V> extends KeySet<K, V> { 512d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected ReferenceKeySet(AbstractHashedMap<K, V> parent) { 514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(parent); 515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 517d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Object[] toArray() { 518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return toArray(new Object[0]); 519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 521d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public <T> T[] toArray(T[] arr) { 522d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // special implementation to handle disappearing keys 523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<K> list = new ArrayList<K>(parent.size()); 524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Iterator<K> it = iterator(); it.hasNext();) { 525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen list.add(it.next()); 526d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return list.toArray(arr); 528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 532d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Values implementation. 534d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen static class ReferenceValues <K,V> extends Values<K, V> { 536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected ReferenceValues(AbstractHashedMap<K, V> parent) { 538d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(parent); 539d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 541d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Object[] toArray() { 542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return toArray(new Object[0]); 543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public <T> T[] toArray(T[] arr) { 546d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // special implementation to handle disappearing values 547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<V> list = new ArrayList<V>(parent.size()); 548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Iterator<V> it = iterator(); it.hasNext();) { 549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen list.add(it.next()); 550d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return list.toArray(arr); 552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 554d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 555d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A MapEntry implementation for the map. 558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If getKey() or getValue() returns null, it means 560d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the mapping is stale and should be removed. 561d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 562d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @since Commons Collections 3.1 563d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 564d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected static class ReferenceEntry <K,V> extends HashEntry<K, V> { 565d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 566d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The parent map 567d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 568d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected final AbstractReferenceMap<K, V> parent; 569d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 570d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected Reference<K> refKey; 571d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected Reference<V> refValue; 572d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 573d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 574d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new entry object for the ReferenceMap. 575d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 576d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param parent the parent map 577d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param next the next entry in the hash bucket 578d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param hashCode the hash code of the key 579d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param key the key 580d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param value the value 581d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 582d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public ReferenceEntry(AbstractReferenceMap<K, V> parent, ReferenceEntry<K, V> next, int hashCode, K key, V value) { 583d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(next, hashCode, null, null); 584d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.parent = parent; 585d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (parent.keyType != HARD) { 586d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen refKey = toReference(parent.keyType, key, hashCode); 587d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 588d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.setKey(key); 589d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 590d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (parent.valueType != HARD) { 591d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen refValue = toReference(parent.valueType, value, hashCode); // the key hashCode is passed in deliberately 592d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 593d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.setValue(value); 594d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 595d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 596d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 597d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 598d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the key from the entry. 599d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This method dereferences weak and soft keys and thus may return null. 600d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 601d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the key, which may be null if it was garbage collected 602d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 603d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public K getKey() { 604d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (parent.keyType > HARD) ? refKey.get() : super.getKey(); 605d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 606d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 607d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 608d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the value from the entry. 609d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This method dereferences weak and soft value and thus may return null. 610d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 611d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the value, which may be null if it was garbage collected 612d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 613d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public V getValue() { 614d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (parent.valueType > HARD) ? refValue.get() : super.getValue(); 615d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 616d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 617d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 618d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the value of the entry. 619d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 620d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param obj the object to store 621d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the previous value 622d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 623d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public V setValue(V obj) { 624d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen V old = getValue(); 625d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (parent.valueType > HARD) { 626d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen refValue.clear(); 627d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen refValue = toReference(parent.valueType, obj, hashCode); 628d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 629d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super.setValue(obj); 630d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 631d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return old; 632d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 633d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 634d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 635d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Compares this map entry to another. 636d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 637d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This implementation uses <code>isEqualKey</code> and 638d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <code>isEqualValue</code> on the main map for comparison. 639d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 640d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param obj the other map entry to compare to 641d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return true if equal, false if not 642d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 643d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean equals(Object obj) { 644d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (obj == this) { 645d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 646d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 647d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (obj instanceof Map.Entry == false) { 648d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 649d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 650d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 651d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Map.Entry entry = (Map.Entry) obj; 652d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Object entryKey = entry.getKey(); // convert to hard reference 653d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Object entryValue = entry.getValue(); // convert to hard reference 654d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if ((entryKey == null) || (entryValue == null)) { 655d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 656d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 657d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // compare using map methods, aiding identity subclass 658d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // note that key is direct access and value is via method 659d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return parent.isEqualKey(entryKey, getKey()) && parent.isEqualValue(entryValue, getValue()); 660d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 661d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 662d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 663d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the hashcode of the entry using temporary hard references. 664d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 665d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This implementation uses <code>hashEntry</code> on the main map. 666d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 667d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the hashcode of the entry 668d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 669d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public int hashCode() { 670d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return parent.hashEntry(getKey(), getValue()); 671d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 672d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 673d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 674d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Constructs a reference of the given type to the given referent. 675d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The reference is registered with the queue for later purging. 676d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 677d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type HARD, SOFT or WEAK 678d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param referent the object to refer to 679d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param hash the hash code of the <i>key</i> of the mapping; 680d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * this number might be different from referent.hashCode() if 681d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the referent represents a value and not a key 682d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 683d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected <T> Reference<T> toReference(int type, T referent, int hash) { 684d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen switch (type) { 685d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen case SOFT: 686d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new SoftRef<T>(hash, referent, parent.queue); 687d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen case WEAK: 688d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new WeakRef<T>(hash, referent, parent.queue); 689d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen default: 690d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new Error("Attempt to create hard reference in ReferenceMap!"); 691d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 692d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 693d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 694d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 695d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Purges the specified reference 696d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 697d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ref the reference to purge 698d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return true or false 699d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 700d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean purge(Reference ref) { 701d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean r = (parent.keyType > HARD) && (refKey == ref); 702d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen r = r || ((parent.valueType > HARD) && (refValue == ref)); 703d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (r) { 704d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (parent.keyType > HARD) { 705d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen refKey.clear(); 706d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 707d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (parent.valueType > HARD) { 708d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen refValue.clear(); 709d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (parent.purgeValues) { 710d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setValue(null); 711d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 712d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 713d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return r; 714d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 715d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 716d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 717d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the next entry in the bucket. 718d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 719d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the next entry in the bucket 720d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 721d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected ReferenceEntry<K, V> next() { 722d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (ReferenceEntry<K, V>) next; 723d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 724d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 725d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 726d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 727d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 728d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The EntrySet iterator. 729d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 730d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen static class ReferenceIteratorBase <K,V> { 731d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 732d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The parent map 733d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 734d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen final AbstractReferenceMap<K, V> parent; 735d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 736d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // These fields keep track of where we are in the table. 737d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int index; 738d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ReferenceEntry<K, V> entry; 739d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ReferenceEntry<K, V> previous; 740d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 741d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // These Object fields provide hard references to the 742d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // current and next entry; this assures that if hasNext() 743d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // returns true, next() will actually return a valid element. 744d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen K nextKey; 745d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen V nextValue; 746d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen K currentKey; 747d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen V currentValue; 748d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 749d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int expectedModCount; 750d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 751d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public ReferenceIteratorBase(AbstractReferenceMap<K, V> parent) { 752d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(); 753d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.parent = parent; 754d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen index = (parent.size() != 0 ? parent.data.length : 0); 755d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // have to do this here! size() invocation above 756d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // may have altered the modCount. 757d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen expectedModCount = parent.modCount; 758d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 759d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 760d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean hasNext() { 761d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkMod(); 762d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (nextNull()) { 763d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ReferenceEntry<K, V> e = entry; 764d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int i = index; 765d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while ((e == null) && (i > 0)) { 766d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen i--; 767d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e = (ReferenceEntry<K, V>) parent.data[i]; 768d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 769d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen entry = e; 770d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen index = i; 771d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (e == null) { 772d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen currentKey = null; 773d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen currentValue = null; 774d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 775d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 776d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen nextKey = e.getKey(); 777d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen nextValue = e.getValue(); 778d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (nextNull()) { 779d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen entry = entry.next(); 780d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 781d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 782d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 783d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 784d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 785d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void checkMod() { 786d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (parent.modCount != expectedModCount) { 787d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new ConcurrentModificationException(); 788d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 789d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 790d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 791d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private boolean nextNull() { 792d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (nextKey == null) || (nextValue == null); 793d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 794d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 795d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected ReferenceEntry<K, V> nextEntry() { 796d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkMod(); 797d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (nextNull() && !hasNext()) { 798d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new NoSuchElementException(); 799d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 800d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen previous = entry; 801d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen entry = entry.next(); 802d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen currentKey = nextKey; 803d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen currentValue = nextValue; 804d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen nextKey = null; 805d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen nextValue = null; 806d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return previous; 807d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 808d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 809d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected ReferenceEntry<K, V> currentEntry() { 810d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkMod(); 811d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return previous; 812d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 813d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 814d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public ReferenceEntry<K, V> superNext() { 815d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return nextEntry(); 816d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 817d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 818d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void remove() { 819d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkMod(); 820d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (previous == null) { 821d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException(); 822d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 823d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen parent.remove(currentKey); 824d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen previous = null; 825d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen currentKey = null; 826d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen currentValue = null; 827d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen expectedModCount = parent.modCount; 828d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 829d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 830d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 831d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 832d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The EntrySet iterator. 833d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 834d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen static class ReferenceEntrySetIterator <K,V> extends ReferenceIteratorBase<K, V> implements Iterator<Map.Entry<K, V>> { 835d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 836d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public ReferenceEntrySetIterator(AbstractReferenceMap<K, V> abstractReferenceMap) { 837d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(abstractReferenceMap); 838d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 839d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 840d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public ReferenceEntry<K, V> next() { 841d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return superNext(); 842d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 843d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 844d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 845d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 846d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 847d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The keySet iterator. 848d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 849d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen static class ReferenceKeySetIterator <K,V> extends ReferenceIteratorBase<K, V> implements Iterator<K> { 850d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 851d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ReferenceKeySetIterator(AbstractReferenceMap<K, V> parent) { 852d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(parent); 853d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 854d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 855d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public K next() { 856d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return nextEntry().getKey(); 857d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 858d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 859d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 860d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 861d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The values iterator. 862d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 863d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen static class ReferenceValuesIterator <K,V> extends ReferenceIteratorBase<K, V> implements Iterator<V> { 864d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 865d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ReferenceValuesIterator(AbstractReferenceMap<K, V> parent) { 866d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(parent); 867d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 868d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 869d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public V next() { 870d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return nextEntry().getValue(); 871d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 872d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 873d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 874d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 875d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The MapIterator implementation. 876d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 877d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen static class ReferenceMapIterator <K,V> extends ReferenceIteratorBase<K, V> implements MapIterator<K, V> { 878d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 879d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected ReferenceMapIterator(AbstractReferenceMap<K, V> parent) { 880d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(parent); 881d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 882d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 883d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public K next() { 884d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return nextEntry().getKey(); 885d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 886d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 887d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public K getKey() { 888d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen HashEntry<K, V> current = currentEntry(); 889d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (current == null) { 890d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID); 891d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 892d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current.getKey(); 893d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 894d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 895d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public V getValue() { 896d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen HashEntry<K, V> current = currentEntry(); 897d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (current == null) { 898d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID); 899d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 900d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current.getValue(); 901d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 902d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 903d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public V setValue(V value) { 904d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen HashEntry<K, V> current = currentEntry(); 905d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (current == null) { 906d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID); 907d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 908d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return current.setValue(value); 909d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 910d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 911d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 912d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 913d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // These two classes store the hashCode of the key of 914d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // of the mapping, so that after they're dequeued a quick 915d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // lookup of the bucket in the table can occur. 916d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 917d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 918d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A soft reference holder. 919d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 920d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen static class SoftRef <T> extends SoftReference<T> { 921d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 922d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the hashCode of the key (even if the reference points to a value) 923d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 924d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private int hash; 925d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 926d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public SoftRef(int hash, T r, ReferenceQueue q) { 927d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(r, q); 928d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.hash = hash; 929d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 930d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 931d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public int hashCode() { 932d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return hash; 933d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 934d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 935d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 936d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 937d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A weak reference holder. 938d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 939d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen static class WeakRef <T> extends WeakReference<T> { 940d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 941d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the hashCode of the key (even if the reference points to a value) 942d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 943d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private int hash; 944d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 945d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public WeakRef(int hash, T r, ReferenceQueue q) { 946d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super(r, q); 947d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.hash = hash; 948d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 949d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 950d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public int hashCode() { 951d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return hash; 952d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 953d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 954d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 955d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen //----------------------------------------------------------------------- 956d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 957d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Replaces the superclass method to store the state of this class. 958d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 959d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Serialization is not one of the JDK's nicest topics. Normal serialization will 960d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * initialise the superclass before the subclass. Sometimes however, this isn't 961d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * what you want, as in this case the <code>put()</code> method on read can be 962d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * affected by subclass state. 963d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 964d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The solution adopted here is to serialize the state data of this class in 965d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * this protected method. This method must be called by the 966d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <code>writeObject()</code> of the first serializable subclass. 967d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 968d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Subclasses may override if they have a specific field that must be present 969d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * on read before this implementation will work. Generally, the read determines 970d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * what must be serialized here, if anything. 971d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 972d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param out the output stream 973d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 974d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void doWriteObject(ObjectOutputStream out) throws IOException { 975d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeInt(keyType); 976d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeInt(valueType); 977d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeBoolean(purgeValues); 978d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeFloat(loadFactor); 979d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeInt(data.length); 980d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (MapIterator it = mapIterator(); it.hasNext();) { 981d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeObject(it.next()); 982d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeObject(it.getValue()); 983d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 984d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeObject(null); // null terminate map 985d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // do not call super.doWriteObject() as code there doesn't work for reference map 986d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 987d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 988d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 989d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Replaces the superclassm method to read the state of this class. 990d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 991d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Serialization is not one of the JDK's nicest topics. Normal serialization will 992d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * initialise the superclass before the subclass. Sometimes however, this isn't 993d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * what you want, as in this case the <code>put()</code> method on read can be 994d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * affected by subclass state. 995d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 996d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The solution adopted here is to deserialize the state data of this class in 997d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * this protected method. This method must be called by the 998d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <code>readObject()</code> of the first serializable subclass. 999d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 1000d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Subclasses may override if the subclass has a specific field that must be present 1001d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * before <code>put()</code> or <code>calculateThreshold()</code> will work correctly. 1002d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1003d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param in the input stream 1004d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1005d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void doReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 1006d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.keyType = in.readInt(); 1007d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.valueType = in.readInt(); 1008d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.purgeValues = in.readBoolean(); 1009d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.loadFactor = in.readFloat(); 1010d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int capacity = in.readInt(); 1011d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen init(); 1012d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen data = new HashEntry[capacity]; 1013d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (true) { 1014d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen K key = (K) in.readObject(); 1015d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (key == null) { 1016d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen break; 1017d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1018d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen V value = (V) in.readObject(); 1019d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen put(key, value); 1020d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1021d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen threshold = calculateThreshold(data.length, loadFactor); 1022d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // do not call super.doReadObject() as code there doesn't work for reference map 1023d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1024d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1025d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 1026