1
14
15 package com.liferay.portal.kernel.util;
16
17 import com.liferay.portal.kernel.memory.EqualityWeakReference;
18 import com.liferay.portal.kernel.memory.FinalizeAction;
19 import com.liferay.portal.kernel.memory.FinalizeManager;
20
21 import java.io.Serializable;
22
23 import java.lang.ref.Reference;
24
25 import java.util.AbstractCollection;
26 import java.util.AbstractSet;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.concurrent.ConcurrentHashMap;
34 import java.util.concurrent.ConcurrentMap;
35
36
41 public class WeakValueConcurrentHashMap<K, V>
42 implements ConcurrentMap<K, V>, Serializable {
43
44 public WeakValueConcurrentHashMap() {
45 _map = new ConcurrentHashMap<K, Reference<V>>();
46 }
47
48 public WeakValueConcurrentHashMap(int initialCapacity) {
49 _map = new ConcurrentHashMap<K, Reference<V>>(initialCapacity);
50 }
51
52 public WeakValueConcurrentHashMap(
53 int initialCapacity, float loadFactor, int concurrencyLevel) {
54 _map = new ConcurrentHashMap<K, Reference<V>>(
55 initialCapacity, loadFactor, concurrencyLevel);
56 }
57
58 public WeakValueConcurrentHashMap(Map<? extends K, ? extends V> map) {
59 _map = new ConcurrentHashMap<K, Reference<V>>();
60
61 putAll(map);
62 }
63
64 public void clear() {
65 _map.clear();
66 }
67
68 public boolean containsKey(Object key) {
69 return _map.containsKey(key);
70 }
71
72 public boolean containsValue(Object value) {
73 return _map.containsValue(new EqualityWeakReference<V>((V)value));
74 }
75
76 public Set<Entry<K, V>> entrySet() {
77 if (_entrySet == null) {
78 _entrySet = new UnwrapEntrySet();
79 }
80
81 return _entrySet;
82 }
83
84 public V get(Object key) {
85 Reference<V> valueReference = _map.get(key);
86
87 if (valueReference != null) {
88 return valueReference.get();
89 }
90
91 return null;
92 }
93
94 public boolean isEmpty() {
95 return _map.isEmpty();
96 }
97
98 public Set<K> keySet() {
99 return _map.keySet();
100 }
101
102 public V put(K key, V value) {
103 Reference<V> valueReference = wrapValue(key, value);
104
105 valueReference = _map.putIfAbsent(key, valueReference);
106
107 if (valueReference != null) {
108 return valueReference.get();
109 }
110
111 return null;
112 }
113
114 public final void putAll(Map<? extends K, ? extends V> map) {
115 for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
116 K key = entry.getKey();
117 V value = entry.getValue();
118
119 Reference<V> valueReference = wrapValue(key, value);
120
121 _map.put(key, valueReference);
122 }
123 }
124
125 public V putIfAbsent(K key, V value) {
126 Reference<V> valueReference = wrapValue(key, value);
127
128 valueReference = _map.putIfAbsent(key, valueReference);
129
130 if (valueReference != null) {
131 return valueReference.get();
132 }
133
134 return null;
135 }
136
137 public V remove(Object key) {
138 Reference<V> valueReference = _map.remove(key);
139
140 if (valueReference != null) {
141 valueReference.get();
142 }
143
144 return null;
145 }
146
147 public boolean remove(Object key, Object value) {
148 Reference<V> valueReference = wrapValue(key, value);
149
150 return _map.remove(key, valueReference);
151 }
152
153 public V replace(K key, V value) {
154 Reference<V> valueReference = wrapValue(key, value);
155
156 valueReference = _map.replace(key, valueReference);
157
158 if (valueReference != null) {
159 return valueReference.get();
160 }
161
162 return null;
163 }
164
165 public boolean replace(K key, V oldValue, V newValue) {
166 Reference<V> oldValueReference = wrapValue(key, oldValue);
167 Reference<V> newValueReference = wrapValue(key, newValue);
168
169 return _map.replace(key, oldValueReference, newValueReference);
170 }
171
172 public int size() {
173 return _map.size();
174 }
175
176 public Collection<V> values() {
177 if (_values == null) {
178 _values = new UnwrapValues();
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 public void clear() {
259 WeakValueConcurrentHashMap.this.clear();
260 }
261
262 public boolean contains(Object obj) {
263 if (!(obj instanceof Map.Entry<?, ?>)) {
264 return false;
265 }
266
267 Map.Entry<K, V> entry = (Map.Entry<K, V>)obj;
268
269 V value = WeakValueConcurrentHashMap.this.get(entry.getKey());
270
271 if ((value != null) && value.equals(entry.getValue())) {
272 return true;
273 }
274 else {
275 return false;
276 }
277 }
278
279 public Iterator<Map.Entry<K, V>> iterator() {
280 return new UnwrapEntryIterator();
281 }
282
283 public boolean remove(Object obj) {
284 if (!(obj instanceof Map.Entry<?, ?>)) {
285 return false;
286 }
287
288 Map.Entry<K, V> entry = (Map.Entry<K, V>)obj;
289
290 return WeakValueConcurrentHashMap.this.remove(
291 entry.getKey(), entry.getValue());
292 }
293
294 public int size() {
295 return WeakValueConcurrentHashMap.this.size();
296 }
297
298 public Object[] toArray() {
299 List<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(size());
300
301 Iterator<Map.Entry<K, V>> iterator = iterator();
302
303 while (iterator.hasNext()) {
304 list.add(iterator.next());
305 }
306
307 return list.toArray();
308 }
309
310 public <T> T[] toArray(T[] array) {
311 List<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(size());
312
313 Iterator<Map.Entry<K, V>> iterator = iterator();
314
315 while (iterator.hasNext()) {
316 list.add(iterator.next());
317 }
318
319 return list.toArray(array);
320 }
321
322 }
323
324 private class UnwrapValueIterator implements Iterator<V> {
325
326 public UnwrapValueIterator() {
327 _iterator = _map.values().iterator();
328 }
329
330 public boolean hasNext() {
331 return _iterator.hasNext();
332 }
333
334 public V next() {
335 Reference<V> valueReference = _iterator.next();
336
337 if (valueReference != null) {
338 return valueReference.get();
339 }
340
341 return null;
342 }
343
344 public void remove() {
345 _iterator.remove();
346 }
347
348 private Iterator<Reference<V>> _iterator;
349
350 }
351
352 private class UnwrapValues extends AbstractCollection<V> {
353
354 public void clear() {
355 WeakValueConcurrentHashMap.this.clear();
356 }
357
358 public boolean contains(Object obj) {
359 return WeakValueConcurrentHashMap.this.containsValue(obj);
360 }
361
362 public Iterator<V> iterator() {
363 return new UnwrapValueIterator();
364 }
365
366 public int size() {
367 return WeakValueConcurrentHashMap.this.size();
368 }
369
370 public Object[] toArray() {
371 List<V> list = new ArrayList<V>();
372
373 Iterator<V> iterator = iterator();
374
375 while (iterator.hasNext()) {
376 list.add(iterator.next());
377 }
378
379 return list.toArray();
380 }
381
382 public <T> T[] toArray(T[] a) {
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(a);
392 }
393
394 }
395
396 }