1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.beanutils;
18
19 import java.util.Collection;
20 import java.util.ConcurrentModificationException;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.Map;
24 import java.util.Set;
25 import java.util.WeakHashMap;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 class WeakFastHashMap<K, V> extends HashMap<K, V> {
65
66
67
68
69 private Map<K, V> map = null;
70
71
72
73
74 private boolean fast = false;
75
76
77
78
79
80
81
82 public WeakFastHashMap() {
83 super();
84 this.map = createMap();
85 }
86
87
88
89
90
91
92 public WeakFastHashMap(final int capacity) {
93 super();
94 this.map = createMap(capacity);
95 }
96
97
98
99
100
101
102
103 public WeakFastHashMap(final int capacity, final float factor) {
104 super();
105 this.map = createMap(capacity, factor);
106 }
107
108
109
110
111
112
113 public WeakFastHashMap(final Map<? extends K, ? extends V> map) {
114 super();
115 this.map = createMap(map);
116 }
117
118
119
120
121
122
123
124
125
126
127 public boolean getFast() {
128 return (this.fast);
129 }
130
131
132
133
134
135
136 public void setFast(final boolean fast) {
137 this.fast = fast;
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 @Override
156 public V get(final Object key) {
157 if (fast) {
158 return (map.get(key));
159 } else {
160 synchronized (map) {
161 return (map.get(key));
162 }
163 }
164 }
165
166
167
168
169
170
171 @Override
172 public int size() {
173 if (fast) {
174 return (map.size());
175 } else {
176 synchronized (map) {
177 return (map.size());
178 }
179 }
180 }
181
182
183
184
185
186
187 @Override
188 public boolean isEmpty() {
189 if (fast) {
190 return (map.isEmpty());
191 } else {
192 synchronized (map) {
193 return (map.isEmpty());
194 }
195 }
196 }
197
198
199
200
201
202
203
204
205 @Override
206 public boolean containsKey(final Object key) {
207 if (fast) {
208 return (map.containsKey(key));
209 } else {
210 synchronized (map) {
211 return (map.containsKey(key));
212 }
213 }
214 }
215
216
217
218
219
220
221
222
223 @Override
224 public boolean containsValue(final Object value) {
225 if (fast) {
226 return (map.containsValue(value));
227 } else {
228 synchronized (map) {
229 return (map.containsValue(value));
230 }
231 }
232 }
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 @Override
250 public V put(final K key, final V value) {
251 if (fast) {
252 synchronized (this) {
253 final Map<K, V> temp = cloneMap(map);
254 final V result = temp.put(key, value);
255 map = temp;
256 return (result);
257 }
258 } else {
259 synchronized (map) {
260 return (map.put(key, value));
261 }
262 }
263 }
264
265
266
267
268
269
270
271 @Override
272 public void putAll(final Map<? extends K, ? extends V> in) {
273 if (fast) {
274 synchronized (this) {
275 final Map<K, V> temp = cloneMap(map);
276 temp.putAll(in);
277 map = temp;
278 }
279 } else {
280 synchronized (map) {
281 map.putAll(in);
282 }
283 }
284 }
285
286
287
288
289
290
291
292
293 @Override
294 public V remove(final Object key) {
295 if (fast) {
296 synchronized (this) {
297 final Map<K, V> temp = cloneMap(map);
298 final V result = temp.remove(key);
299 map = temp;
300 return (result);
301 }
302 } else {
303 synchronized (map) {
304 return (map.remove(key));
305 }
306 }
307 }
308
309
310
311
312 @Override
313 public void clear() {
314 if (fast) {
315 synchronized (this) {
316 map = createMap();
317 }
318 } else {
319 synchronized (map) {
320 map.clear();
321 }
322 }
323 }
324
325
326
327
328
329
330
331
332
333
334
335
336
337 @Override
338 public boolean equals(final Object o) {
339
340 if (o == this) {
341 return (true);
342 } else if (!(o instanceof Map)) {
343 return (false);
344 }
345 final Map<?, ?> mo = (Map<?, ?>) o;
346
347
348 if (fast) {
349 if (mo.size() != map.size()) {
350 return (false);
351 }
352 for (final Map.Entry<K, V> e : map.entrySet()) {
353 final K key = e.getKey();
354 final V value = e.getValue();
355 if (value == null) {
356 if (!(mo.get(key) == null && mo.containsKey(key))) {
357 return (false);
358 }
359 } else {
360 if (!value.equals(mo.get(key))) {
361 return (false);
362 }
363 }
364 }
365 return (true);
366
367 } else {
368 synchronized (map) {
369 if (mo.size() != map.size()) {
370 return (false);
371 }
372 for (final Map.Entry<K, V> e : map.entrySet()) {
373 final K key = e.getKey();
374 final V value = e.getValue();
375 if (value == null) {
376 if (!(mo.get(key) == null && mo.containsKey(key))) {
377 return (false);
378 }
379 } else {
380 if (!value.equals(mo.get(key))) {
381 return (false);
382 }
383 }
384 }
385 return (true);
386 }
387 }
388 }
389
390
391
392
393
394
395
396
397 @Override
398 public int hashCode() {
399 if (fast) {
400 int h = 0;
401 for (final Map.Entry<K, V> e : map.entrySet()) {
402 h += e.hashCode();
403 }
404 return (h);
405 } else {
406 synchronized (map) {
407 int h = 0;
408 for (final Map.Entry<K, V> e : map.entrySet()) {
409 h += e.hashCode();
410 }
411 return (h);
412 }
413 }
414 }
415
416
417
418
419
420
421
422 @Override
423 public Object clone() {
424 WeakFastHashMap<K, V> results = null;
425 if (fast) {
426 results = new WeakFastHashMap<K, V>(map);
427 } else {
428 synchronized (map) {
429 results = new WeakFastHashMap<K, V>(map);
430 }
431 }
432 results.setFast(getFast());
433 return (results);
434 }
435
436
437
438
439
440
441
442
443
444 @Override
445 public Set<Map.Entry<K, V>> entrySet() {
446 return new EntrySet();
447 }
448
449
450
451
452
453 @Override
454 public Set<K> keySet() {
455 return new KeySet();
456 }
457
458
459
460
461
462 @Override
463 public Collection<V> values() {
464 return new Values();
465 }
466
467
468
469
470 protected Map<K, V> createMap() {
471 return new WeakHashMap<K, V>();
472 }
473
474 protected Map<K, V> createMap(final int capacity) {
475 return new WeakHashMap<K, V>(capacity);
476 }
477
478 protected Map<K, V> createMap(final int capacity, final float factor) {
479 return new WeakHashMap<K, V>(capacity, factor);
480 }
481
482 protected Map<K, V> createMap(final Map<? extends K, ? extends V> map) {
483 return new WeakHashMap<K, V>(map);
484 }
485
486 protected Map<K, V> cloneMap(final Map<? extends K, ? extends V> map) {
487 return createMap(map);
488 }
489
490
491
492
493
494
495
496
497
498 private abstract class CollectionView<E> implements Collection<E> {
499
500 public CollectionView() {
501 }
502
503 protected abstract Collection<E> get(Map<K, V> map);
504 protected abstract E iteratorNext(Map.Entry<K, V> entry);
505
506
507 public void clear() {
508 if (fast) {
509 synchronized (WeakFastHashMap.this) {
510 map = createMap();
511 }
512 } else {
513 synchronized (map) {
514 get(map).clear();
515 }
516 }
517 }
518
519 public boolean remove(final Object o) {
520 if (fast) {
521 synchronized (WeakFastHashMap.this) {
522 final Map<K, V> temp = cloneMap(map);
523 final boolean r = get(temp).remove(o);
524 map = temp;
525 return r;
526 }
527 } else {
528 synchronized (map) {
529 return get(map).remove(o);
530 }
531 }
532 }
533
534 public boolean removeAll(final Collection<?> o) {
535 if (fast) {
536 synchronized (WeakFastHashMap.this) {
537 final Map<K, V> temp = cloneMap(map);
538 final boolean r = get(temp).removeAll(o);
539 map = temp;
540 return r;
541 }
542 } else {
543 synchronized (map) {
544 return get(map).removeAll(o);
545 }
546 }
547 }
548
549 public boolean retainAll(final Collection<?> o) {
550 if (fast) {
551 synchronized (WeakFastHashMap.this) {
552 final Map<K, V> temp = cloneMap(map);
553 final boolean r = get(temp).retainAll(o);
554 map = temp;
555 return r;
556 }
557 } else {
558 synchronized (map) {
559 return get(map).retainAll(o);
560 }
561 }
562 }
563
564 public int size() {
565 if (fast) {
566 return get(map).size();
567 } else {
568 synchronized (map) {
569 return get(map).size();
570 }
571 }
572 }
573
574
575 public boolean isEmpty() {
576 if (fast) {
577 return get(map).isEmpty();
578 } else {
579 synchronized (map) {
580 return get(map).isEmpty();
581 }
582 }
583 }
584
585 public boolean contains(final Object o) {
586 if (fast) {
587 return get(map).contains(o);
588 } else {
589 synchronized (map) {
590 return get(map).contains(o);
591 }
592 }
593 }
594
595 public boolean containsAll(final Collection<?> o) {
596 if (fast) {
597 return get(map).containsAll(o);
598 } else {
599 synchronized (map) {
600 return get(map).containsAll(o);
601 }
602 }
603 }
604
605 public <T> T[] toArray(final T[] o) {
606 if (fast) {
607 return get(map).toArray(o);
608 } else {
609 synchronized (map) {
610 return get(map).toArray(o);
611 }
612 }
613 }
614
615 public Object[] toArray() {
616 if (fast) {
617 return get(map).toArray();
618 } else {
619 synchronized (map) {
620 return get(map).toArray();
621 }
622 }
623 }
624
625
626 @Override
627 public boolean equals(final Object o) {
628 if (o == this) {
629 return true;
630 }
631 if (fast) {
632 return get(map).equals(o);
633 } else {
634 synchronized (map) {
635 return get(map).equals(o);
636 }
637 }
638 }
639
640 @Override
641 public int hashCode() {
642 if (fast) {
643 return get(map).hashCode();
644 } else {
645 synchronized (map) {
646 return get(map).hashCode();
647 }
648 }
649 }
650
651 public boolean add(final E o) {
652 throw new UnsupportedOperationException();
653 }
654
655 public boolean addAll(final Collection<? extends E> c) {
656 throw new UnsupportedOperationException();
657 }
658
659 public Iterator<E> iterator() {
660 return new CollectionViewIterator();
661 }
662
663 private class CollectionViewIterator implements Iterator<E> {
664
665 private Map<K, V> expected;
666 private Map.Entry<K, V> lastReturned = null;
667 private final Iterator<Map.Entry<K, V>> iterator;
668
669 public CollectionViewIterator() {
670 this.expected = map;
671 this.iterator = expected.entrySet().iterator();
672 }
673
674 public boolean hasNext() {
675 if (expected != map) {
676 throw new ConcurrentModificationException();
677 }
678 return iterator.hasNext();
679 }
680
681 public E next() {
682 if (expected != map) {
683 throw new ConcurrentModificationException();
684 }
685 lastReturned = iterator.next();
686 return iteratorNext(lastReturned);
687 }
688
689 public void remove() {
690 if (lastReturned == null) {
691 throw new IllegalStateException();
692 }
693 if (fast) {
694 synchronized (WeakFastHashMap.this) {
695 if (expected != map) {
696 throw new ConcurrentModificationException();
697 }
698 WeakFastHashMap.this.remove(lastReturned.getKey());
699 lastReturned = null;
700 expected = map;
701 }
702 } else {
703 iterator.remove();
704 lastReturned = null;
705 }
706 }
707 }
708 }
709
710
711
712
713 private class KeySet extends CollectionView<K> implements Set<K> {
714
715 @Override
716 protected Collection<K> get(final Map<K, V> map) {
717 return map.keySet();
718 }
719
720 @Override
721 protected K iteratorNext(final Map.Entry<K, V> entry) {
722 return entry.getKey();
723 }
724
725 }
726
727
728
729
730 private class Values extends CollectionView<V> {
731
732 @Override
733 protected Collection<V> get(final Map<K, V> map) {
734 return map.values();
735 }
736
737 @Override
738 protected V iteratorNext(final Map.Entry<K, V> entry) {
739 return entry.getValue();
740 }
741 }
742
743
744
745
746 private class EntrySet extends CollectionView<Map.Entry<K, V>> implements Set<Map.Entry<K, V>> {
747
748 @Override
749 protected Collection<Map.Entry<K, V>> get(final Map<K, V> map) {
750 return map.entrySet();
751 }
752
753 @Override
754 protected Map.Entry<K, V> iteratorNext(final Map.Entry<K, V> entry) {
755 return entry;
756 }
757
758 }
759
760 }