001
014
015 package com.liferay.portal.kernel.util;
016
017 import com.liferay.portal.kernel.memory.EqualityWeakReference;
018 import com.liferay.portal.kernel.memory.FinalizeAction;
019 import com.liferay.portal.kernel.memory.FinalizeManager;
020
021 import java.io.Serializable;
022
023 import java.lang.ref.Reference;
024
025 import java.util.AbstractCollection;
026 import java.util.AbstractSet;
027 import java.util.ArrayList;
028 import java.util.Collection;
029 import java.util.Iterator;
030 import java.util.List;
031 import java.util.Map;
032 import java.util.Set;
033 import java.util.concurrent.ConcurrentHashMap;
034 import java.util.concurrent.ConcurrentMap;
035
036
039 public class WeakValueConcurrentHashMap<K, V>
040 implements ConcurrentMap<K, V>, Serializable {
041
042 public WeakValueConcurrentHashMap() {
043 _map = new ConcurrentHashMap<K, Reference<V>>();
044 }
045
046 public WeakValueConcurrentHashMap(int initialCapacity) {
047 _map = new ConcurrentHashMap<K, Reference<V>>(initialCapacity);
048 }
049
050 public WeakValueConcurrentHashMap(
051 int initialCapacity, float loadFactor, int concurrencyLevel) {
052
053 _map = new ConcurrentHashMap<K, Reference<V>>(
054 initialCapacity, loadFactor, concurrencyLevel);
055 }
056
057 public WeakValueConcurrentHashMap(Map<? extends K, ? extends V> map) {
058 _map = new ConcurrentHashMap<K, Reference<V>>();
059
060 putAll(map);
061 }
062
063 public void clear() {
064 _map.clear();
065 }
066
067 public boolean containsKey(Object key) {
068 return _map.containsKey(key);
069 }
070
071 public boolean containsValue(Object value) {
072 return _map.containsValue(new EqualityWeakReference<V>((V)value));
073 }
074
075 public Set<Entry<K, V>> entrySet() {
076 if (_entrySet == null) {
077 _entrySet = new UnwrapEntrySet();
078 }
079
080 return _entrySet;
081 }
082
083 public V get(Object key) {
084 Reference<V> valueReference = _map.get(key);
085
086 if (valueReference != null) {
087 return valueReference.get();
088 }
089
090 return null;
091 }
092
093 public boolean isEmpty() {
094 return _map.isEmpty();
095 }
096
097 public Set<K> keySet() {
098 return _map.keySet();
099 }
100
101 public V put(K key, V value) {
102 Reference<V> valueReference = wrapValue(key, value);
103
104 valueReference = _map.putIfAbsent(key, valueReference);
105
106 if (valueReference != null) {
107 return valueReference.get();
108 }
109
110 return null;
111 }
112
113 public final void putAll(Map<? extends K, ? extends V> map) {
114 for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
115 K key = entry.getKey();
116 V value = entry.getValue();
117
118 Reference<V> valueReference = wrapValue(key, value);
119
120 _map.put(key, valueReference);
121 }
122 }
123
124 public V putIfAbsent(K key, V value) {
125 Reference<V> valueReference = wrapValue(key, value);
126
127 valueReference = _map.putIfAbsent(key, valueReference);
128
129 if (valueReference != null) {
130 return valueReference.get();
131 }
132
133 return null;
134 }
135
136 public V remove(Object key) {
137 Reference<V> valueReference = _map.remove(key);
138
139 if (valueReference != null) {
140 return valueReference.get();
141 }
142
143 return null;
144 }
145
146 public boolean remove(Object key, Object value) {
147 Reference<V> valueReference = wrapValue(key, value);
148
149 return _map.remove(key, valueReference);
150 }
151
152 public V replace(K key, V value) {
153 Reference<V> valueReference = wrapValue(key, value);
154
155 valueReference = _map.replace(key, valueReference);
156
157 if (valueReference != null) {
158 return valueReference.get();
159 }
160
161 return null;
162 }
163
164 public boolean replace(K key, V oldValue, V newValue) {
165 Reference<V> oldValueReference = wrapValue(key, oldValue);
166 Reference<V> newValueReference = wrapValue(key, newValue);
167
168 return _map.replace(key, oldValueReference, newValueReference);
169 }
170
171 public int size() {
172 return _map.size();
173 }
174
175 public Collection<V> values() {
176 if (_values == null) {
177 _values = new UnwrapValues();
178 }
179
180 return _values;
181 }
182
183 protected Reference<V> wrapValue(Object key, Object value) {
184 return FinalizeManager.register(
185 (V)value, new RemoveEntryFinalizeAction((K)key));
186 }
187
188 private transient Set<Map.Entry<K, V>> _entrySet;
189 private final ConcurrentMap<K, Reference<V>> _map;
190 private transient Collection<V> _values;
191
192 private class RemoveEntryFinalizeAction implements FinalizeAction {
193
194 public RemoveEntryFinalizeAction(K key) {
195 _key = key;
196 }
197
198 public void doFinalize() {
199 remove(_key);
200 }
201
202 private final K _key;
203
204 }
205
206 private class UnwrapEntry implements Map.Entry<K, V> {
207
208 public UnwrapEntry(Entry<K, Reference<V>> entry) {
209 _entry = entry;
210 }
211
212 public K getKey() {
213 return _entry.getKey();
214 }
215
216 public V getValue() {
217 Reference<V> valueReference = _entry.getValue();
218
219 if (valueReference != null) {
220 return valueReference.get();
221 }
222
223 return null;
224 }
225
226 public V setValue(V value) {
227 return WeakValueConcurrentHashMap.this.put(_entry.getKey(), value);
228 }
229
230 private Map.Entry<K, Reference<V>> _entry;
231
232 }
233
234 private class UnwrapEntryIterator implements Iterator<Map.Entry<K, V>> {
235
236 public UnwrapEntryIterator() {
237 _iterator = _map.entrySet().iterator();
238 }
239
240 public boolean hasNext() {
241 return _iterator.hasNext();
242 }
243
244 public Entry<K, V> next() {
245 return new UnwrapEntry(_iterator.next());
246 }
247
248 public void remove() {
249 _iterator.remove();
250 }
251
252 private Iterator<Map.Entry<K, Reference<V>>> _iterator;
253
254 }
255
256 private class UnwrapEntrySet extends AbstractSet<Map.Entry<K, V>> {
257
258 @Override
259 public void clear() {
260 WeakValueConcurrentHashMap.this.clear();
261 }
262
263 @Override
264 public boolean contains(Object obj) {
265 if (!(obj instanceof Map.Entry<?, ?>)) {
266 return false;
267 }
268
269 Map.Entry<K, V> entry = (Map.Entry<K, V>)obj;
270
271 V value = WeakValueConcurrentHashMap.this.get(entry.getKey());
272
273 if ((value != null) && value.equals(entry.getValue())) {
274 return true;
275 }
276 else {
277 return false;
278 }
279 }
280
281 @Override
282 public Iterator<Map.Entry<K, V>> iterator() {
283 return new UnwrapEntryIterator();
284 }
285
286 @Override
287 public boolean remove(Object obj) {
288 if (!(obj instanceof Map.Entry<?, ?>)) {
289 return false;
290 }
291
292 Map.Entry<K, V> entry = (Map.Entry<K, V>)obj;
293
294 return WeakValueConcurrentHashMap.this.remove(
295 entry.getKey(), entry.getValue());
296 }
297
298 @Override
299 public int size() {
300 return WeakValueConcurrentHashMap.this.size();
301 }
302
303 @Override
304 public Object[] toArray() {
305 List<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(size());
306
307 Iterator<Map.Entry<K, V>> iterator = iterator();
308
309 while (iterator.hasNext()) {
310 list.add(iterator.next());
311 }
312
313 return list.toArray();
314 }
315
316 @Override
317 public <T> T[] toArray(T[] array) {
318 List<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(size());
319
320 Iterator<Map.Entry<K, V>> iterator = iterator();
321
322 while (iterator.hasNext()) {
323 list.add(iterator.next());
324 }
325
326 return list.toArray(array);
327 }
328
329 }
330
331 private class UnwrapValueIterator implements Iterator<V> {
332
333 public UnwrapValueIterator() {
334 _iterator = _map.values().iterator();
335 }
336
337 public boolean hasNext() {
338 return _iterator.hasNext();
339 }
340
341 public V next() {
342 Reference<V> valueReference = _iterator.next();
343
344 if (valueReference != null) {
345 return valueReference.get();
346 }
347
348 return null;
349 }
350
351 public void remove() {
352 _iterator.remove();
353 }
354
355 private Iterator<Reference<V>> _iterator;
356
357 }
358
359 private class UnwrapValues extends AbstractCollection<V> {
360
361 @Override
362 public void clear() {
363 WeakValueConcurrentHashMap.this.clear();
364 }
365
366 @Override
367 public boolean contains(Object obj) {
368 return WeakValueConcurrentHashMap.this.containsValue(obj);
369 }
370
371 @Override
372 public Iterator<V> iterator() {
373 return new UnwrapValueIterator();
374 }
375
376 @Override
377 public int size() {
378 return WeakValueConcurrentHashMap.this.size();
379 }
380
381 @Override
382 public Object[] toArray() {
383 List<V> list = new ArrayList<V>();
384
385 Iterator<V> iterator = iterator();
386
387 while (iterator.hasNext()) {
388 list.add(iterator.next());
389 }
390
391 return list.toArray();
392 }
393
394 @Override
395 public <T> T[] toArray(T[] a) {
396 List<V> list = new ArrayList<V>();
397
398 Iterator<V> iterator = iterator();
399
400 while (iterator.hasNext()) {
401 list.add(iterator.next());
402 }
403
404 return list.toArray(a);
405 }
406
407 }
408
409 }