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 * @see java.lang.ref.Reference
069 *
070 * @since 3.0 (previously in main package v2.1)
071 * @version $Id: ReferenceMap.html 887892 2013-11-24 13:43:45Z tn $
072 */
073public class ReferenceMap<K, V> extends AbstractReferenceMap<K, V> implements Serializable {
074
075    /** Serialization version */
076    private static final long serialVersionUID = 1555089888138299607L;
077
078    /**
079     * Constructs a new <code>ReferenceMap</code> that will
080     * use hard references to keys and soft references to values.
081     */
082    public ReferenceMap() {
083        super(ReferenceStrength.HARD, ReferenceStrength.SOFT, DEFAULT_CAPACITY,
084                DEFAULT_LOAD_FACTOR, false);
085    }
086
087    /**
088     * Constructs a new <code>ReferenceMap</code> that will
089     * use the specified types of references.
090     *
091     * @param keyType  the type of reference to use for keys;
092     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
093     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
094     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
095     * @param valueType  the type of reference to use for values;
096     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
097     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
098     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
099     */
100    public ReferenceMap(final ReferenceStrength keyType, final ReferenceStrength valueType) {
101        super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
102    }
103
104    /**
105     * Constructs a new <code>ReferenceMap</code> that will
106     * use the specified types of references.
107     *
108     * @param keyType  the type of reference to use for keys;
109     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
110     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
111     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
112     * @param valueType  the type of reference to use for values;
113     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
114     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
115     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
116     * @param purgeValues should the value be automatically purged when the
117     *   key is garbage collected
118     */
119    public ReferenceMap(final ReferenceStrength keyType, final ReferenceStrength valueType, final boolean purgeValues) {
120        super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, purgeValues);
121    }
122
123    /**
124     * Constructs a new <code>ReferenceMap</code> with the
125     * specified reference types, load factor and initial
126     * capacity.
127     *
128     * @param keyType  the type of reference to use for keys;
129     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
130     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
131     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
132     * @param valueType  the type of reference to use for values;
133     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
134     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
135     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
136     * @param capacity  the initial capacity for the map
137     * @param loadFactor  the load factor for the map
138     */
139    public ReferenceMap(final ReferenceStrength keyType, final ReferenceStrength valueType, final int capacity,
140            final float loadFactor) {
141        super(keyType, valueType, capacity, loadFactor, false);
142    }
143
144    /**
145     * Constructs a new <code>ReferenceMap</code> with the
146     * specified reference types, load factor and initial
147     * capacity.
148     *
149     * @param keyType  the type of reference to use for keys;
150     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
151     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
152     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
153     * @param valueType  the type of reference to use for values;
154     *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
155     *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
156     *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
157     * @param capacity  the initial capacity for the map
158     * @param loadFactor  the load factor for the map
159     * @param purgeValues  should the value be automatically purged when the
160     *   key is garbage collected
161     */
162    public ReferenceMap(final ReferenceStrength keyType, final ReferenceStrength valueType, final int capacity,
163            final float loadFactor, final boolean purgeValues) {
164        super(keyType, valueType, capacity, loadFactor, purgeValues);
165    }
166
167    //-----------------------------------------------------------------------
168    /**
169     * Write the map out using a custom routine.
170     */
171    private void writeObject(final ObjectOutputStream out) throws IOException {
172        out.defaultWriteObject();
173        doWriteObject(out);
174    }
175
176    /**
177     * Read the map in using a custom routine.
178     */
179    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
180        in.defaultReadObject();
181        doReadObject(in);
182    }
183
184}