001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.collections4.map;
018
019import java.io.IOException;
020import java.io.ObjectInputStream;
021import java.io.ObjectOutputStream;
022import java.io.Serializable;
023
024/**
025 * A <code>Map</code> implementation that allows mappings to be
026 * removed by the garbage collector.
027 * <p>
028 * When you construct a <code>ReferenceMap</code>, you can specify what kind
029 * of references are used to store the map's keys and values.
030 * If non-hard references are used, then the garbage collector can remove
031 * mappings if a key or value becomes unreachable, or if the JVM's memory is
032 * running low. For information on how the different reference types behave,
033 * see {@link java.lang.ref.Reference Reference}.
034 * <p>
035 * Different types of references can be specified for keys and values.
036 * The keys can be configured to be weak but the values hard,
037 * in which case this class will behave like a
038 * <a href="http://java.sun.com/j2se/1.4/docs/api/java/util/WeakHashMap.html">
039 * <code>WeakHashMap</code></a>. However, you can also specify hard keys and
040 * weak values, or any other combination. The default constructor uses
041 * hard keys and soft values, providing a memory-sensitive cache.
042 * <p>
043 * This map is similar to
044 * {@link org.apache.commons.collections4.map.ReferenceIdentityMap ReferenceIdentityMap}.
045 * It differs in that keys and values in this class are compared using <code>equals()</code>.
046 * <p>
047 * This {@link java.util.Map Map} implementation does <i>not</i> allow null elements.
048 * Attempting to add a null key or value to the map will raise a <code>NullPointerException</code>.
049 * <p>
050 * This implementation is not synchronized.
051 * You can use {@link java.util.Collections#synchronizedMap} to
052 * provide synchronized access to a <code>ReferenceMap</code>.
053 * Remember that synchronization will not stop the garbage collector removing entries.
054 * <p>
055 * All the available iterators can be reset back to the start by casting to
056 * <code>ResettableIterator</code> and calling <code>reset()</code>.
057 * <p>
058 * <strong>Note that ReferenceMap is not synchronized and is not thread-safe.</strong>
059 * If you wish to use this map from multiple threads concurrently, you must use
060 * appropriate synchronization. The simplest approach is to wrap this map
061 * using {@link java.util.Collections#synchronizedMap}. This class may throw
062 * exceptions when accessed by concurrent threads without synchronization.
063 * <p>
064 * NOTE: As from Commons Collections 3.1 this map extends <code>AbstractReferenceMap</code>
065 * (previously it extended AbstractMap). As a result, the implementation is now
066 * extensible and provides a <code>MapIterator</code>.
067 *
068 * @param <K> the type of the keys in the map
069 * @param <V> the type of the values in the map
070 *
071 * @see java.lang.ref.Reference
072 * @since 3.0 (previously in main package v2.1)
073 */
074public class ReferenceMap<K, V> extends AbstractReferenceMap<K, V> implements Serializable {
075
076    /** Serialization version */
077    private static final long serialVersionUID = 1555089888138299607L;
078
079    /**
080     * Constructs a new <code>ReferenceMap</code> that will
081     * use hard references to keys and soft references to values.
082     */
083    public ReferenceMap() {
084        super(ReferenceStrength.HARD, ReferenceStrength.SOFT, DEFAULT_CAPACITY,
085                DEFAULT_LOAD_FACTOR, false);
086    }
087
088    /**
089     * Constructs a new <code>ReferenceMap</code> that will
090     * use the specified types of references.
091     *
092     * @param keyType  the type of reference to use for keys;
093     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
094     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
095     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
096     * @param valueType  the type of reference to use for values;
097     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
098     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
099     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
100     */
101    public ReferenceMap(final ReferenceStrength keyType, final ReferenceStrength valueType) {
102        super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
103    }
104
105    /**
106     * Constructs a new <code>ReferenceMap</code> that will
107     * use the specified types of references.
108     *
109     * @param keyType  the type of reference to use for keys;
110     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
111     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
112     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
113     * @param valueType  the type of reference to use for values;
114     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
115     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
116     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
117     * @param purgeValues should the value be automatically purged when the
118     *   key is garbage collected
119     */
120    public ReferenceMap(final ReferenceStrength keyType, final ReferenceStrength valueType, final boolean purgeValues) {
121        super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, purgeValues);
122    }
123
124    /**
125     * Constructs a new <code>ReferenceMap</code> with the
126     * specified reference types, load factor and initial
127     * capacity.
128     *
129     * @param keyType  the type of reference to use for keys;
130     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
131     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
132     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
133     * @param valueType  the type of reference to use for values;
134     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
135     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
136     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
137     * @param capacity  the initial capacity for the map
138     * @param loadFactor  the load factor for the map
139     */
140    public ReferenceMap(final ReferenceStrength keyType, final ReferenceStrength valueType, final int capacity,
141            final float loadFactor) {
142        super(keyType, valueType, capacity, loadFactor, false);
143    }
144
145    /**
146     * Constructs a new <code>ReferenceMap</code> with the
147     * specified reference types, load factor and initial
148     * capacity.
149     *
150     * @param keyType  the type of reference to use for keys;
151     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
152     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
153     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
154     * @param valueType  the type of reference to use for values;
155     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
156     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
157     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
158     * @param capacity  the initial capacity for the map
159     * @param loadFactor  the load factor for the map
160     * @param purgeValues  should the value be automatically purged when the
161     *   key is garbage collected
162     */
163    public ReferenceMap(final ReferenceStrength keyType, final ReferenceStrength valueType, final int capacity,
164            final float loadFactor, final boolean purgeValues) {
165        super(keyType, valueType, capacity, loadFactor, purgeValues);
166    }
167
168    //-----------------------------------------------------------------------
169    /**
170     * Write the map out using a custom routine.
171     *
172     * @param out  the output stream
173     * @throws IOException if an error occurs while writing to the stream
174     */
175    private void writeObject(final ObjectOutputStream out) throws IOException {
176        out.defaultWriteObject();
177        doWriteObject(out);
178    }
179
180    /**
181     * Read the map in using a custom routine.
182     *
183     * @param in the input stream
184     * @throws IOException if an error occurs while reading from the stream
185     * @throws ClassNotFoundException if an object read from the stream can not be loaded
186     */
187    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
188        in.defaultReadObject();
189        doReadObject(in);
190    }
191
192}