View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.map;
18  
19  import java.io.IOException;
20  import java.io.ObjectInputStream;
21  import java.io.ObjectOutputStream;
22  import java.io.Serializable;
23  import java.lang.ref.Reference;
24  import java.util.Map;
25  
26  /**
27   * A {@code Map} implementation that allows mappings to be
28   * removed by the garbage collector.
29   * <p>
30   * When you construct a {@code ReferenceMap}, you can specify what kind
31   * of references are used to store the map's keys and values.
32   * If non-hard references are used, then the garbage collector can remove
33   * mappings if a key or value becomes unreachable, or if the JVM's memory is
34   * running low. For information on how the different reference types behave,
35   * see {@link Reference Reference}.
36   * </p>
37   * <p>
38   * Different types of references can be specified for keys and values.
39   * The keys can be configured to be weak but the values hard,
40   * in which case this class will behave like a
41   * <a href="https://docs.oracle.com/javase/8/docs/api/java/util/WeakHashMap.html">
42   * {@code WeakHashMap}</a>. However, you can also specify hard keys and
43   * weak values, or any other combination. The default constructor uses
44   * hard keys and soft values, providing a memory-sensitive cache.
45   * </p>
46   * <p>
47   * This map is similar to
48   * {@link ReferenceIdentityMap ReferenceIdentityMap}.
49   * It differs in that keys and values in this class are compared using {@code equals()}.
50   * </p>
51   * <p>
52   * This {@link Map Map} implementation does <em>not</em> allow null elements.
53   * Attempting to add a null key or value to the map will raise a {@code NullPointerException}.
54   * </p>
55   * <p>
56   * This implementation is not synchronized.
57   * You can use {@link java.util.Collections#synchronizedMap} to
58   * provide synchronized access to a {@code ReferenceMap}.
59   * Remember that synchronization will not stop the garbage collector removing entries.
60   * </p>
61   * <p>
62   * All the available iterators can be reset back to the start by casting to
63   * {@code ResettableIterator} and calling {@code reset()}.
64   * </p>
65   * <p>
66   * <strong>Note that ReferenceMap is not synchronized and is not thread-safe.</strong>
67   * If you wish to use this map from multiple threads concurrently, you must use
68   * appropriate synchronization. The simplest approach is to wrap this map
69   * using {@link java.util.Collections#synchronizedMap}. This class may throw
70   * exceptions when accessed by concurrent threads without synchronization.
71   * </p>
72   * <p>
73   * NOTE: As from Commons Collections 3.1 this map extends {@code AbstractReferenceMap}
74   * (previously it extended AbstractMap). As a result, the implementation is now
75   * extensible and provides a {@code MapIterator}.
76   * </p>
77   *
78   * @param <K> The type of the keys in the map
79   * @param <V> The type of the values in the map
80   * @see java.lang.ref.Reference
81   * @since 3.0 (previously in main package v2.1)
82   */
83  public class ReferenceMap<K, V> extends AbstractReferenceMap<K, V> implements Serializable {
84  
85      /** Serialization version */
86      private static final long serialVersionUID = 1555089888138299607L;
87  
88      /**
89       * Constructs a new {@code ReferenceMap} that will
90       * use hard references to keys and soft references to values.
91       */
92      public ReferenceMap() {
93          super(ReferenceStrength.HARD, ReferenceStrength.SOFT, DEFAULT_CAPACITY,
94                  DEFAULT_LOAD_FACTOR, false);
95      }
96  
97      /**
98       * Constructs a new {@code ReferenceMap} that will
99       * use the specified types of references.
100      *
101      * @param keyType  The type of reference to use for keys;
102      *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
103      *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
104      *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
105      * @param valueType  The type of reference to use for values;
106      *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
107      *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
108      *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
109      */
110     public ReferenceMap(final ReferenceStrength keyType, final ReferenceStrength valueType) {
111         super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
112     }
113 
114     /**
115      * Constructs a new {@code ReferenceMap} that will
116      * use the specified types of references.
117      *
118      * @param keyType  The type of reference to use for keys;
119      *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
120      *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
121      *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
122      * @param valueType  The type of reference to use for values;
123      *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
124      *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
125      *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
126      * @param purgeValues should the value be automatically purged when the
127      *   key is garbage collected
128      */
129     public ReferenceMap(final ReferenceStrength keyType, final ReferenceStrength valueType, final boolean purgeValues) {
130         super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, purgeValues);
131     }
132 
133     /**
134      * Constructs a new {@code ReferenceMap} with the
135      * specified reference types, load factor and initial
136      * capacity.
137      *
138      * @param keyType  The type of reference to use for keys;
139      *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
140      *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
141      *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
142      * @param valueType  The type of reference to use for values;
143      *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
144      *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
145      *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
146      * @param capacity  The initial capacity for the map
147      * @param loadFactor  The load factor for the map
148      */
149     public ReferenceMap(final ReferenceStrength keyType, final ReferenceStrength valueType, final int capacity,
150             final float loadFactor) {
151         super(keyType, valueType, capacity, loadFactor, false);
152     }
153 
154     /**
155      * Constructs a new {@code ReferenceMap} with the
156      * specified reference types, load factor and initial
157      * capacity.
158      *
159      * @param keyType  The type of reference to use for keys;
160      *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
161      *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
162      *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
163      * @param valueType  The type of reference to use for values;
164      *   must be {@link AbstractReferenceMap.ReferenceStrength#HARD HARD},
165      *   {@link AbstractReferenceMap.ReferenceStrength#SOFT SOFT},
166      *   {@link AbstractReferenceMap.ReferenceStrength#WEAK WEAK}
167      * @param capacity  The initial capacity for the map
168      * @param loadFactor  The load factor for the map
169      * @param purgeValues  should the value be automatically purged when the
170      *   key is garbage collected
171      */
172     public ReferenceMap(final ReferenceStrength keyType, final ReferenceStrength valueType, final int capacity,
173             final float loadFactor, final boolean purgeValues) {
174         super(keyType, valueType, capacity, loadFactor, purgeValues);
175     }
176 
177     /**
178      * Deserializes the map in using a custom routine.
179      *
180      * @param in The input stream
181      * @throws IOException Thrown if an error occurs while reading from the stream
182      * @throws ClassNotFoundException if an object read from the stream cannot be loaded
183      */
184     private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
185         in.defaultReadObject();
186         doReadObject(in);
187     }
188 
189     /**
190      * Serializes this object to an ObjectOutputStream.
191      *
192      * @param out The target ObjectOutputStream.
193      * @throws IOException thrown when an I/O errors occur writing to the target stream.
194      */
195     private void writeObject(final ObjectOutputStream out) throws IOException {
196         out.defaultWriteObject();
197         doWriteObject(out);
198     }
199 
200 }