AbstractReferenceMap.java revision d7955ce24d294fb2014c59d11fca184471056f44
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