-
Notifications
You must be signed in to change notification settings - Fork 108
/
ConcurrentHashMapNullSafe.java
117 lines (111 loc) · 5.17 KB
/
ConcurrentHashMapNullSafe.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package com.cedarsoftware.util;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* A thread-safe implementation of {@link java.util.concurrent.ConcurrentMap} that supports
* {@code null} keys and {@code null} values by using internal sentinel objects.
* <p>
* {@code ConcurrentHashMapNullSafe} extends {@link AbstractConcurrentNullSafeMap} and uses a
* {@link ConcurrentHashMap} as its backing implementation. This class retains all the advantages
* of {@code ConcurrentHashMap} (e.g., high concurrency, thread safety, and performance) while
* enabling safe handling of {@code null} keys and values.
* </p>
*
* <h2>Key Features</h2>
* <ul>
* <li>Thread-safe and highly concurrent.</li>
* <li>Supports {@code null} keys and {@code null} values through internal sentinel objects.</li>
* <li>Adheres to the {@link java.util.Map} and {@link java.util.concurrent.ConcurrentMap} contracts.</li>
* <li>Provides multiple constructors to control initial capacity, load factor, and populate from another map.</li>
* </ul>
*
* <h2>Usage Example</h2>
* <pre>{@code
* // Create an empty ConcurrentHashMapNullSafe
* ConcurrentHashMapNullSafe<String, String> map = new ConcurrentHashMapNullSafe<>();
* map.put(null, "nullKey");
* map.put("key", null);
*
* // Populate from another map
* Map<String, String> existingMap = Map.of("a", "b", "c", "d");
* ConcurrentHashMapNullSafe<String, String> populatedMap = new ConcurrentHashMapNullSafe<>(existingMap);
*
* System.out.println(map.get(null)); // Outputs: nullKey
* System.out.println(map.get("key")); // Outputs: null
* System.out.println(populatedMap); // Outputs: {a=b, c=d}
* }</pre>
*
* @param <K> the type of keys maintained by this map
* @param <V> the type of mapped values
*
* @author John DeRegnaucourt
* <br>
* Copyright (c) Cedar Software LLC
* <br><br>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <br><br>
* <a href="http://www.apache.org/licenses/LICENSE-2.0">License</a>
* <br><br>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* @see ConcurrentHashMap
* @see AbstractConcurrentNullSafeMap
*/
public class ConcurrentHashMapNullSafe<K, V> extends AbstractConcurrentNullSafeMap<K, V> {
/**
* Constructs a new, empty {@code ConcurrentHashMapNullSafe} with the default initial capacity (16)
* and load factor (0.75).
* <p>
* This constructor creates a thread-safe map suitable for general-purpose use, retaining the
* concurrency properties of {@link ConcurrentHashMap} while supporting {@code null} keys and values.
* </p>
*/
public ConcurrentHashMapNullSafe() {
super(new ConcurrentHashMap<>());
}
/**
* Constructs a new, empty {@code ConcurrentHashMapNullSafe} with the specified initial capacity
* and default load factor (0.75).
*
* @param initialCapacity the initial capacity. The implementation performs internal sizing
* to accommodate this many elements.
* @throws IllegalArgumentException if the initial capacity is negative
*/
public ConcurrentHashMapNullSafe(int initialCapacity) {
super(new ConcurrentHashMap<>(initialCapacity));
}
/**
* Constructs a new, empty {@code ConcurrentHashMapNullSafe} with the specified initial capacity
* and load factor.
*
* @param initialCapacity the initial capacity. The implementation performs internal sizing
* to accommodate this many elements.
* @param loadFactor the load factor threshold, used to control resizing. Resizing may be
* performed when the average number of elements per bin exceeds this threshold.
* @throws IllegalArgumentException if the initial capacity is negative or the load factor is nonpositive
*/
public ConcurrentHashMapNullSafe(int initialCapacity, float loadFactor) {
super(new ConcurrentHashMap<>(initialCapacity, loadFactor));
}
/**
* Constructs a new {@code ConcurrentHashMapNullSafe} with the same mappings as the specified map.
* <p>
* This constructor copies all mappings from the given map into the new {@code ConcurrentHashMapNullSafe}.
* The mappings are inserted in the order returned by the source map's {@code entrySet} iterator.
* </p>
*
* @param m the map whose mappings are to be placed in this map
* @throws NullPointerException if the specified map is {@code null}
*/
public ConcurrentHashMapNullSafe(Map<? extends K, ? extends V> m) {
super(new ConcurrentHashMap<>());
putAll(m);
}
// No need to override any methods from AbstractConcurrentNullSafeMap
// as all required functionalities are already inherited.
}