@@ -98,7 +98,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
98
98
* Late binding entry set.
99
99
*/
100
100
@ Nullable
101
- private Set <Map .Entry <K , V >> entrySet ;
101
+ private volatile Set <Map .Entry <K , V >> entrySet ;
102
102
103
103
104
104
/**
@@ -167,8 +167,8 @@ public ConcurrentReferenceHashMap(int initialCapacity, float loadFactor, int con
167
167
* @param referenceType the reference type used for entries (soft or weak)
168
168
*/
169
169
@ SuppressWarnings ("unchecked" )
170
- public ConcurrentReferenceHashMap (int initialCapacity , float loadFactor , int concurrencyLevel ,
171
- ReferenceType referenceType ) {
170
+ public ConcurrentReferenceHashMap (
171
+ int initialCapacity , float loadFactor , int concurrencyLevel , ReferenceType referenceType ) {
172
172
173
173
Assert .isTrue (initialCapacity >= 0 , "Initial capacity must not be negative" );
174
174
Assert .isTrue (loadFactor > 0f , "Load factor must be positive" );
@@ -215,7 +215,7 @@ protected ReferenceManager createReferenceManager() {
215
215
* @return the resulting hash code
216
216
*/
217
217
protected int getHash (@ Nullable Object o ) {
218
- int hash = o == null ? 0 : o .hashCode ();
218
+ int hash = ( o != null ? o .hashCode () : 0 );
219
219
hash += (hash << 15 ) ^ 0xffffcd7d ;
220
220
hash ^= (hash >>> 10 );
221
221
hash += (hash << 3 );
@@ -247,8 +247,8 @@ public boolean containsKey(@Nullable Object key) {
247
247
248
248
@ Nullable
249
249
private Entry <K , V > getEntryIfAvailable (@ Nullable Object key ) {
250
- Reference <K , V > reference = getReference (key , Restructure .WHEN_NECESSARY );
251
- return (reference != null ? reference .get () : null );
250
+ Reference <K , V > ref = getReference (key , Restructure .WHEN_NECESSARY );
251
+ return (ref != null ? ref .get () : null );
252
252
}
253
253
254
254
/**
@@ -281,7 +281,7 @@ private V put(@Nullable final K key, @Nullable final V value, final boolean over
281
281
return doTask (key , new Task <V >(TaskOption .RESTRUCTURE_BEFORE , TaskOption .RESIZE ) {
282
282
@ Override
283
283
@ Nullable
284
- protected V execute (@ Nullable Reference <K , V > reference , @ Nullable Entry <K , V > entry , @ Nullable Entries entries ) {
284
+ protected V execute (@ Nullable Reference <K , V > ref , @ Nullable Entry <K , V > entry , @ Nullable Entries entries ) {
285
285
if (entry != null ) {
286
286
V oldValue = entry .getValue ();
287
287
if (overwriteExisting ) {
@@ -302,10 +302,10 @@ public V remove(Object key) {
302
302
return doTask (key , new Task <V >(TaskOption .RESTRUCTURE_AFTER , TaskOption .SKIP_IF_EMPTY ) {
303
303
@ Override
304
304
@ Nullable
305
- protected V execute (@ Nullable Reference <K , V > reference , @ Nullable Entry <K , V > entry ) {
305
+ protected V execute (@ Nullable Reference <K , V > ref , @ Nullable Entry <K , V > entry ) {
306
306
if (entry != null ) {
307
- if (reference != null ) {
308
- reference .release ();
307
+ if (ref != null ) {
308
+ ref .release ();
309
309
}
310
310
return entry .value ;
311
311
}
@@ -318,10 +318,10 @@ protected V execute(@Nullable Reference<K, V> reference, @Nullable Entry<K, V> e
318
318
public boolean remove (Object key , final Object value ) {
319
319
Boolean result = doTask (key , new Task <Boolean >(TaskOption .RESTRUCTURE_AFTER , TaskOption .SKIP_IF_EMPTY ) {
320
320
@ Override
321
- protected Boolean execute (@ Nullable Reference <K , V > reference , @ Nullable Entry <K , V > entry ) {
321
+ protected Boolean execute (@ Nullable Reference <K , V > ref , @ Nullable Entry <K , V > entry ) {
322
322
if (entry != null && ObjectUtils .nullSafeEquals (entry .getValue (), value )) {
323
- if (reference != null ) {
324
- reference .release ();
323
+ if (ref != null ) {
324
+ ref .release ();
325
325
}
326
326
return true ;
327
327
}
@@ -335,7 +335,7 @@ protected Boolean execute(@Nullable Reference<K, V> reference, @Nullable Entry<K
335
335
public boolean replace (K key , final V oldValue , final V newValue ) {
336
336
Boolean result = doTask (key , new Task <Boolean >(TaskOption .RESTRUCTURE_BEFORE , TaskOption .SKIP_IF_EMPTY ) {
337
337
@ Override
338
- protected Boolean execute (@ Nullable Reference <K , V > reference , @ Nullable Entry <K , V > entry ) {
338
+ protected Boolean execute (@ Nullable Reference <K , V > ref , @ Nullable Entry <K , V > entry ) {
339
339
if (entry != null && ObjectUtils .nullSafeEquals (entry .getValue (), oldValue )) {
340
340
entry .setValue (newValue );
341
341
return true ;
@@ -352,7 +352,7 @@ public V replace(K key, final V value) {
352
352
return doTask (key , new Task <V >(TaskOption .RESTRUCTURE_BEFORE , TaskOption .SKIP_IF_EMPTY ) {
353
353
@ Override
354
354
@ Nullable
355
- protected V execute (@ Nullable Reference <K , V > reference , @ Nullable Entry <K , V > entry ) {
355
+ protected V execute (@ Nullable Reference <K , V > ref , @ Nullable Entry <K , V > entry ) {
356
356
if (entry != null ) {
357
357
V oldValue = entry .getValue ();
358
358
entry .setValue (value );
@@ -393,11 +393,23 @@ public int size() {
393
393
}
394
394
395
395
@ Override
396
- public Set <java .util .Map .Entry <K , V >> entrySet () {
397
- if (this .entrySet == null ) {
398
- this .entrySet = new EntrySet ();
396
+ public boolean isEmpty () {
397
+ for (Segment segment : this .segments ) {
398
+ if (segment .getCount () > 0 ) {
399
+ return false ;
400
+ }
399
401
}
400
- return this .entrySet ;
402
+ return true ;
403
+ }
404
+
405
+ @ Override
406
+ public Set <Map .Entry <K , V >> entrySet () {
407
+ Set <Map .Entry <K , V >> entrySet = this .entrySet ;
408
+ if (entrySet == null ) {
409
+ entrySet = new EntrySet ();
410
+ this .entrySet = entrySet ;
411
+ }
412
+ return entrySet ;
401
413
}
402
414
403
415
@ Nullable
@@ -512,8 +524,8 @@ public <T> T doTask(final int hash, @Nullable final Object key, final Task<T> ta
512
524
try {
513
525
final int index = getIndex (hash , this .references );
514
526
final Reference <K , V > head = this .references [index ];
515
- Reference <K , V > reference = findInChain (head , key , hash );
516
- Entry <K , V > entry = (reference != null ? reference .get () : null );
527
+ Reference <K , V > ref = findInChain (head , key , hash );
528
+ Entry <K , V > entry = (ref != null ? ref .get () : null );
517
529
Entries entries = new Entries () {
518
530
@ Override
519
531
public void add (@ Nullable V value ) {
@@ -524,7 +536,7 @@ public void add(@Nullable V value) {
524
536
Segment .this .count ++;
525
537
}
526
538
};
527
- return task .execute (reference , entry , entries );
539
+ return task .execute (ref , entry , entries );
528
540
}
529
541
finally {
530
542
unlock ();
@@ -559,19 +571,18 @@ public void clear() {
559
571
* @param allowResize if resizing is permitted
560
572
*/
561
573
protected final void restructureIfNecessary (boolean allowResize ) {
562
- boolean needsResize = (( this .count > 0 ) && ( this .count >= this .resizeThreshold ) );
563
- Reference <K , V > reference = this .referenceManager .pollForPurge ();
564
- if (( reference != null ) || (needsResize && allowResize )) {
574
+ boolean needsResize = (this .count > 0 && this .count >= this .resizeThreshold );
575
+ Reference <K , V > ref = this .referenceManager .pollForPurge ();
576
+ if (ref != null || (needsResize && allowResize )) {
565
577
lock ();
566
578
try {
567
579
int countAfterRestructure = this .count ;
568
-
569
580
Set <Reference <K , V >> toPurge = Collections .emptySet ();
570
- if (reference != null ) {
581
+ if (ref != null ) {
571
582
toPurge = new HashSet <>();
572
- while (reference != null ) {
573
- toPurge .add (reference );
574
- reference = this .referenceManager .pollForPurge ();
583
+ while (ref != null ) {
584
+ toPurge .add (ref );
585
+ ref = this .referenceManager .pollForPurge ();
575
586
}
576
587
}
577
588
countAfterRestructure -= toPurge .size ();
@@ -587,24 +598,25 @@ protected final void restructureIfNecessary(boolean allowResize) {
587
598
}
588
599
589
600
// Either create a new table or reuse the existing one
590
- Reference <K , V >[] restructured = (resizing ? createReferenceArray (restructureSize ) : this .references );
601
+ Reference <K , V >[] restructured =
602
+ (resizing ? createReferenceArray (restructureSize ) : this .references );
591
603
592
604
// Restructure
593
605
for (int i = 0 ; i < this .references .length ; i ++) {
594
- reference = this .references [i ];
606
+ ref = this .references [i ];
595
607
if (!resizing ) {
596
608
restructured [i ] = null ;
597
609
}
598
- while (reference != null ) {
599
- if (!toPurge .contains (reference )) {
600
- Entry <K , V > entry = reference .get ();
610
+ while (ref != null ) {
611
+ if (!toPurge .contains (ref )) {
612
+ Entry <K , V > entry = ref .get ();
601
613
if (entry != null ) {
602
- int index = getIndex (reference .getHash (), restructured );
614
+ int index = getIndex (ref .getHash (), restructured );
603
615
restructured [index ] = this .referenceManager .createReference (
604
- entry , reference .getHash (), restructured [index ]);
616
+ entry , ref .getHash (), restructured [index ]);
605
617
}
606
618
}
607
- reference = reference .getNext ();
619
+ ref = ref .getNext ();
608
620
}
609
621
}
610
622
@@ -622,8 +634,8 @@ protected final void restructureIfNecessary(boolean allowResize) {
622
634
}
623
635
624
636
@ Nullable
625
- private Reference <K , V > findInChain (Reference <K , V > reference , @ Nullable Object key , int hash ) {
626
- Reference <K , V > currRef = reference ;
637
+ private Reference <K , V > findInChain (Reference <K , V > ref , @ Nullable Object key , int hash ) {
638
+ Reference <K , V > currRef = ref ;
627
639
while (currRef != null ) {
628
640
if (currRef .getHash () == hash ) {
629
641
Entry <K , V > entry = currRef .get ();
@@ -774,26 +786,26 @@ public boolean hasOption(TaskOption option) {
774
786
775
787
/**
776
788
* Execute the task.
777
- * @param reference the found reference or {@code null}
778
- * @param entry the found entry or {@code null}
789
+ * @param ref the found reference ( or {@code null})
790
+ * @param entry the found entry ( or {@code null})
779
791
* @param entries access to the underlying entries
780
792
* @return the result of the task
781
793
* @see #execute(Reference, Entry)
782
794
*/
783
795
@ Nullable
784
- protected T execute (@ Nullable Reference <K , V > reference , @ Nullable Entry <K , V > entry , @ Nullable Entries entries ) {
785
- return execute (reference , entry );
796
+ protected T execute (@ Nullable Reference <K , V > ref , @ Nullable Entry <K , V > entry , @ Nullable Entries entries ) {
797
+ return execute (ref , entry );
786
798
}
787
799
788
800
/**
789
801
* Convenience method that can be used for tasks that do not need access to {@link Entries}.
790
- * @param reference the found reference or {@code null}
791
- * @param entry the found entry or {@code null}
802
+ * @param ref the found reference ( or {@code null})
803
+ * @param entry the found entry ( or {@code null})
792
804
* @return the result of the task
793
805
* @see #execute(Reference, Entry, Entries)
794
806
*/
795
807
@ Nullable
796
- protected T execute (@ Nullable Reference <K , V > reference , @ Nullable Entry <K , V > entry ) {
808
+ protected T execute (@ Nullable Reference <K , V > ref , @ Nullable Entry <K , V > entry ) {
797
809
return null ;
798
810
}
799
811
}
@@ -834,9 +846,9 @@ public Iterator<Map.Entry<K, V>> iterator() {
834
846
@ Override
835
847
public boolean contains (@ Nullable Object o ) {
836
848
if (o instanceof Map .Entry <?, ?>) {
837
- Map .Entry <?, ?> entry = (java . util . Map .Entry <?, ?>) o ;
838
- Reference <K , V > reference = ConcurrentReferenceHashMap .this .getReference (entry .getKey (), Restructure .NEVER );
839
- Entry <K , V > otherEntry = (reference != null ? reference .get () : null );
849
+ Map .Entry <?, ?> entry = (Map .Entry <?, ?>) o ;
850
+ Reference <K , V > ref = ConcurrentReferenceHashMap .this .getReference (entry .getKey (), Restructure .NEVER );
851
+ Entry <K , V > otherEntry = (ref != null ? ref .get () : null );
840
852
if (otherEntry != null ) {
841
853
return ObjectUtils .nullSafeEquals (otherEntry .getValue (), otherEntry .getValue ());
842
854
}
0 commit comments