Class MultiKeyMap<V>
- Type Parameters:
V- the type of values stored in the map
- All Implemented Interfaces:
ConcurrentMap<Object,,V> Map<Object,V>
MultiKeyMap allows storing and retrieving values using multiple keys. Unlike traditional maps that use a single key, this map can handle keys with any number of components, making it ideal for complex lookup scenarios like user permissions, configuration trees, and caching systems.
Key Features:
- N-Dimensional Keys: Support for keys with any number of components (1, 2, 3, ... N).
- High Performance: Zero-allocation polymorphic storage, polynomial rolling hash, and optimized hash computation — no GC/heap pressure for gets in flat cases.
- Thread-Safe: Lock-free reads with auto-tuned stripe locking that scales with your server cores, similar to ConcurrentHashMap.
- Map Interface Compatible: Supports single-key operations via the standard Map interface (get()/put() automatically unpack Collections/Arrays into multi-keys).
- Flexible API: Var-args methods for convenient multi-key operations (getMultiKey()/putMultiKey() with many keys).
- Smart Collection Handling: Configurable behavior for Collections via
MultiKeyMap.CollectionKeyMode— change the default automatic unpacking capability as needed. - N-Dimensional Array Expansion: Nested arrays of any depth are automatically flattened recursively into multi-keys.
- Cross-Container Equivalence: Arrays and ordered Collections (Lists) with equivalent structure are treated as identical keys.
- Set Support: Sets are treated as order-agnostic containers. Sets only match other Sets (not Lists/Arrays), and matching is independent of element order.
Dimensional Behavior Control:
MultiKeyMap provides revolutionary control over how dimensions are handled through the flattenDimensions parameter:
- Structure-Preserving Mode (default, flattenDimensions = false): Different structural depths remain distinct keys. Arrays/Collections with different nesting levels create separate entries.
- Dimension-Flattening Mode (flattenDimensions = true): All equivalent flat representations are treated as identical keys, regardless of original container structure.
Performance Characteristics:
- Lock-Free Reads: Get operations require no locking for optimal concurrent performance
- Auto-Tuned Stripe Locking: Write operations use stripe locking that adapts to your server's core count
- Zero-Allocation Gets: No temporary objects created during retrieval operations
- Polymorphic Storage: Efficient memory usage adapts storage format based on key complexity
- Simple Keys Mode: Optional performance optimization that skips nested structure checks when keys are known to be flat
Capacity and Size Limits:
MultiKeyMap uses AtomicLong internally for size tracking, allowing it to scale well beyond
the traditional Integer.MAX_VALUE (231-1) limitation:
- Actual Capacity: The map can hold many more than 231-1 entries, limited only by heap memory.
- size() Method: Due to the
Map.size()interface contract requiringint, thesize()method returnsInteger.MAX_VALUEif the actual size exceeds this limit. - longSize() Method: Use
longSize()to get the exact count for very large maps. This method returns the true size as alongwithout the 231-1 cap. - Memory Requirements: Storing 231 entries requires approximately 200-300 GB of heap memory (assuming ~100-150 bytes per entry including bucket overhead).
- Practical Limit: On modern servers with 512GB-2TB RAM, maps with billions of entries are feasible.
Performance Complexity:
MultiKeyMap provides constant-time performance for most operations:
- get/put/remove/containsKey: O(k) average, O(k + c) worst case
where k = key components, c = chain length (typically 1-3) - size/longSize/isEmpty: O(1) - atomic counter access
- clear: O(capacity) - must clear all buckets
- keySet/values/entrySet: O(n) - creates snapshot of n entries
Key Processing Complexity:
- Simple keys (String, Integer): O(1) hash and comparison
- Multi-dimensional keys: O(k) where k = number of components
- Nested collections: O(k × m) where k = depth, m = average size per level
- Set keys: ~3-4x slower than List keys (order-agnostic hashing)
Value-Based vs Type-Based Equality:
MultiKeyMap provides two equality modes for key comparison, controlled via the valueBasedEquality parameter:
- Value-Based Equality (default, valueBasedEquality = true): Cross-type numeric comparisons work naturally. Integer 1 equals Long 1L equals Double 1.0. This mode is ideal for configuration lookups and user-friendly APIs.
- Type-Based Equality (valueBasedEquality = false): Strict type checking - Integer 1 ≠ Long 1L. This mode provides traditional Java Map semantics and maximum performance.
Value-Based Equality Edge Cases:
- NaN Behavior: In value-based mode,
NaN == NaNreturns true (unlike Java's default). This ensures consistent key lookups with floating-point values. - Zero Handling:
+0.0 == -0.0returns true in both modes (standard Java behavior). - BigDecimal Precision: Doubles are converted via
new BigDecimal(number.toString()). This means0.1dequalsBigDecimal("0.1")but NOTBigDecimal(0.1)(the latter has binary rounding errors). - Infinity Handling: Comparing
Double.POSITIVE_INFINITYorNEGATIVE_INFINITYto BigDecimal returns false (BigDecimal cannot represent infinity). - Atomic Types: In type-based mode, only identical atomic types match (AtomicInteger ≠ Integer). In value-based mode, atomic types participate in numeric families (AtomicInteger(1) == Integer(1)).
Case Sensitivity for CharSequences:
MultiKeyMap provides configurable case sensitivity for CharSequence keys (String, StringBuilder, etc.),
controlled via the caseSensitive parameter:
- Case-Sensitive Mode (default, caseSensitive = true): CharSequences are compared using their standard equals() methods. "Hello" and "hello" are different keys.
- Case-Insensitive Mode (caseSensitive = false): All CharSequence instances are compared case-insensitively. "Hello", "HELLO", and "hello" are treated as the same key.
API Overview:
MultiKeyMap provides two complementary APIs:
- Map Interface: Use as
Map<Object, V>for compatibility with existing code and single-key operations - MultiKeyMap API: Declare as
MultiKeyMap<V>to access powerful var-args methods for multidimensional operations
Usage Examples:
// Basic multi-dimensional usage
MultiKeyMap<String> map = new MultiKeyMap<>();
map.putMultiKey("user-config", "user123", "settings", "theme");
String theme = map.getMultiKey("user123", "settings", "theme");
// Cross-container equivalence
map.put(new String[]{"key1", "key2"}, "value1"); // Array key
String value = map.get(Arrays.asList("key1", "key2")); // Collection lookup - same key!
// Structure-preserving vs flattening modes
MultiKeyMap<String> structured = MultiKeyMap.<String>builder().flattenDimensions(false).build(); // Structure-preserving (default)
MultiKeyMap<String> flattened = MultiKeyMap.<String>builder().flattenDimensions(true).build(); // Dimension-flattening
// Performance optimization for flat keys (no nested arrays/collections)
MultiKeyMap<String> fast = MultiKeyMap.<String>builder()
.simpleKeysMode(true) // Skip nested structure checks for maximum performance
.capacity(50000) // Pre-size for known data volume
.build();
// Value-based vs Type-based equality
MultiKeyMap<String> valueMap = MultiKeyMap.<String>builder().valueBasedEquality(true).build(); // Default
valueMap.putMultiKey("found", 1, 2L, 3.0); // Mixed numeric types
String result = valueMap.getMultiKey(1L, 2, 3); // Found! Cross-type numeric matching
MultiKeyMap<String> typeMap = MultiKeyMap.<String>builder().valueBasedEquality(false).build();
typeMap.putMultiKey("int-key", 1, 2, 3);
String missing = typeMap.getMultiKey(1L, 2L, 3L); // null - different types don't match
// Case-insensitive string keys
MultiKeyMap<String> caseInsensitive = MultiKeyMap.<String>builder().caseSensitive(false).build();
caseInsensitive.putMultiKey("value", "USER", "Settings", "THEME");
String found = caseInsensitive.getMultiKey("user", "settings", "theme"); // Found! Case doesn't matter
// Set support - order-agnostic matching
MultiKeyMap<String> map = new MultiKeyMap<>();
Set<String> coordinates = new HashSet<>(Arrays.asList("x", "y", "z"));
map.put(coordinates, "value");
// Sets match other Sets regardless of order or Set type
Set<String> lookup1 = new LinkedHashSet<>(Arrays.asList("z", "x", "y")); // Different order
assertEquals("value", map.get(lookup1)); // Found! Order doesn't matter
Set<String> lookup2 = new TreeSet<>(Arrays.asList("y", "z", "x")); // Different Set type
assertEquals("value", map.get(lookup2)); // Found! Set type doesn't matter
// Sets don't match Lists/Arrays (semantic distinction)
List<String> listLookup = Arrays.asList("x", "y", "z");
assertNull(map.get(listLookup)); // Not found - Lists don't match Sets
For comprehensive examples and advanced usage patterns, see the user guide documentation.
Set Semantics:
Sets are treated as order-agnostic containers with the following behavior:
- Order-Agnostic Matching: Sets match other Sets regardless of element order.
Set.of(1,2,3)equalsSet.of(3,2,1). - Type Independence: All Set types (HashSet, TreeSet, LinkedHashSet) are treated equivalently based on their elements.
- Semantic Distinction: Sets only match other Sets - they do not match Lists or Arrays even with identical elements.
- Nested Sets: Sets within arrays, lists, or other sets are properly handled with order-agnostic semantics.
- Performance: Set operations are approximately 3-4x slower than List operations due to order-agnostic hash computation.
- Empty Sets: Empty Sets are distinct from empty Lists/Arrays.
Complex Key Examples with Sets:
Sets can be combined with other key types in multi-dimensional keys:
MultiKeyMap<String> map = new MultiKeyMap<>();
// Example 1: Set combined with Object[] as a multi-key
Set<String> permissions = new HashSet<>(Arrays.asList("read", "write", "execute"));
Object[] userKey = new Object[]{"user123", permissions, "config"};
map.put(userKey, "user-permissions-config");
// Lookup works with different Set order
Set<String> samePermsDiffOrder = new LinkedHashSet<>(Arrays.asList("execute", "read", "write"));
Object[] lookupKey = new Object[]{"user123", samePermsDiffOrder, "config"};
assertEquals("user-permissions-config", map.get(lookupKey)); // Found!
// Example 2: Set combined with List as a multi-key
Set<Integer> tags = Set.of(100, 200, 300); // Order doesn't matter
List<String> path = Arrays.asList("api", "v1", "users"); // Order DOES matter
map.putMultiKey("endpoint-handler", tags, path);
// Lookup with different Set order but same List order
Set<Integer> sameTags = Set.of(300, 100, 200); // Different order - still matches
List<String> samePath = Arrays.asList("api", "v1", "users"); // Same order required
assertEquals("endpoint-handler", map.getMultiKey(sameTags, samePath)); // Found!
// Different List order will NOT match
List<String> differentPath = Arrays.asList("v1", "api", "users"); // Different order
assertNull(map.getMultiKey(sameTags, differentPath)); // Not found!
- Author:
- John DeRegnaucourt ([email protected])
Copyright (c) Cedar Software LLC
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
License
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.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classBuilder for creating configured MultiKeyMap instances.static enumControls how Collections are treated when used as keys in MultiKeyMap. -
Constructor Summary
ConstructorsConstructorDescriptionMultiKeyMap(int capacity) MultiKeyMap(int capacity, float loadFactor) MultiKeyMap(MultiKeyMap<? extends V> source) -
Method Summary
Modifier and TypeMethodDescriptionstatic <V> MultiKeyMap.Builder<V>builder()voidclear()Removes all the mappings from this map.Attempts to compute a mapping for the specified key and its current mapped value (ornullif there is no current mapping).computeIfAbsent(Object key, Function<? super Object, ? extends V> mappingFunction) If the specified key is not already associated with a value, attempts to compute its value using the given mapping function and enters it into this map unlessnull.computeIfPresent(Object key, BiFunction<? super Object, ? super V, ? extends V> remappingFunction) If the specified key is not already associated with a value, attempts to compute a new mapping given the key and its current mapped value.booleancontainsKey(Object key) Returnstrueif this map contains a mapping for the specified key.booleancontainsMultiKey(Object... keys) Returnstrueif this map contains a mapping for the specified multidimensional key using var-args syntax.booleancontainsMultiKey(Object k1, Object k2) Optimized 2-key containsKey check with zero allocation using ThreadLocal array.booleancontainsMultiKey(Object k1, Object k2, Object k3) Optimized 3-key containsKey check with zero allocation using ThreadLocal array.booleancontainsMultiKey(Object k1, Object k2, Object k3, Object k4) Optimized 4-key containsKey check with zero allocation using ThreadLocal array.booleanOptimized 5-key containsKey check with zero allocation using ThreadLocal array.booleancontainsValue(Object value) Returnstrueif this map maps one or more keys to the specified value.entrySet()Returns aSetview of the mappings contained in this map.booleanCompares the specified object with this map for equality.Returns the value to which the specified key is mapped, ornullif this map contains no mapping for the key.intReturns the initial capacity setting for this map.booleanReturns the current case sensitivity setting for CharSequence comparisons.Returns the current collection key mode setting.booleanReturns the current dimension flattening setting.floatReturns the load factor setting for this map.getMultiKey(Object... keys) Retrieves the value associated with the specified multidimensional key using var-args syntax.getMultiKey(Object k1, Object k2) Optimized 2-key lookup with zero allocation using ThreadLocal array.getMultiKey(Object k1, Object k2, Object k3) Optimized 3-key lookup with zero allocation using ThreadLocal array.getMultiKey(Object k1, Object k2, Object k3, Object k4) Optimized 4-key lookup with zero allocation using ThreadLocal array.Optimized 5-key lookup with zero allocation using ThreadLocal array.booleanReturns the current simple keys mode setting.booleanReturns the value-based equality setting for numeric keys.inthashCode()Returns the hash code value for this map.booleanisEmpty()Returnstrueif this map contains no key-value mappings.keySet()Returns aSetview of the keys contained in this map.longlongSize()Returns the exact number of key-value mappings in this map as along.If the specified key is not already associated with a value or is associated with null, associates it with the given non-null value.voidPrints detailed contention statistics for this map's stripe locking system to the logger.Associates the specified value with the specified key in this map.voidCopies all the mappings from the specified map to this map.putIfAbsent(Object key, V value) If the specified key is not already associated with a value, associates it with the given value.putMultiKey(V value, Object... keys) Associates the specified value with the specified multidimensional key using var-args syntax.static ObjectreconstructKey(Object[] in) Reconstructs keys as native structures (List, Set, or single items) for serialization.Removes the mapping for the specified key from this map if it is present.booleanRemoves the entry for a key only if it is currently mapped to the specified value.removeMultiKey(Object... keys) Removes the mapping for the specified multidimensional key using var-args syntax.Replaces the entry for the specified key only if it is currently mapped to some value.booleanReplaces the entry for the specified key only if currently mapped to the specified value.intsize()Returns the number of key-value mappings in this map.toString()Returns a string representation of this map.values()Returns aCollectionview of the values contained in this map.Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, waitMethods inherited from interface java.util.concurrent.ConcurrentMap
forEach, getOrDefault, replaceAll
-
Constructor Details
-
MultiKeyMap
-
MultiKeyMap
public MultiKeyMap() -
MultiKeyMap
public MultiKeyMap(int capacity) -
MultiKeyMap
public MultiKeyMap(int capacity, float loadFactor)
-
-
Method Details
-
builder
-
getCollectionKeyMode
Returns the current collection key mode setting.This mode determines how Collections are treated when used as keys in this map.
- Returns:
- the current
MultiKeyMap.CollectionKeyMode- either COLLECTIONS_EXPANDED (default) where Collections are automatically unpacked into multi-key entries, or COLLECTIONS_NOT_EXPANDED where Collections are treated as single key objects - See Also:
-
getFlattenDimensions
public boolean getFlattenDimensions()Returns the current dimension flattening setting.This setting controls how nested arrays and collections are handled when used as keys.
- Returns:
trueif dimension flattening is enabled (all equivalent flat representations are treated as identical keys regardless of original container structure),falseif structure-preserving mode is used (default, where different structural depths remain distinct keys)
-
getSimpleKeysMode
public boolean getSimpleKeysMode()Returns the current simple keys mode setting.This performance optimization setting indicates whether the map assumes keys do not contain nested arrays or collections.
- Returns:
trueif simple keys mode is enabled (nested structure checks are skipped for maximum performance),falseif normal operation with full nested structure support
-
getCaseSensitive
public boolean getCaseSensitive()Returns the current case sensitivity setting for CharSequence comparisons.This setting controls how CharSequence instances (String, StringBuilder, etc.) are compared within keys.
- Returns:
trueif case-sensitive comparison is enabled (default),falseif case-insensitive comparison is used- Since:
- 3.6.0
-
getCapacity
public int getCapacity()Returns the initial capacity setting for this map.This is the capacity value specified when the map was built, which was used to determine the initial internal bucket array size.
- Returns:
- the initial capacity
-
getLoadFactor
public float getLoadFactor()Returns the load factor setting for this map.The load factor determines when the map will resize. A value of 0.75 means the map will resize when it's 75% full.
- Returns:
- the load factor
-
getValueBasedEquality
public boolean getValueBasedEquality()Returns the value-based equality setting for numeric keys.When enabled, numeric keys are compared by value rather than type. For example, Integer(42) will match Long(42) when value-based equality is enabled.
- Returns:
trueif value-based equality is enabled (default),falseif type-based equality is used
-
getMultiKey
Retrieves the value associated with the specified multidimensional key using var-args syntax.This is a convenience method that allows easy multi-key lookups without having to pass arrays or collections. The keys are treated as separate dimensions of a multi-key.
- Parameters:
keys- the key components to look up. Can be null or empty (treated as null key), single key, or multiple key components- Returns:
- the value associated with the multi-key, or
nullif no mapping exists - See Also:
-
getMultiKey
Optimized 2-key lookup with zero allocation using ThreadLocal array.- Parameters:
k1- first key componentk2- second key component- Returns:
- the value associated with the multi-key, or
nullif no mapping exists
-
getMultiKey
Optimized 3-key lookup with zero allocation using ThreadLocal array.- Parameters:
k1- first key componentk2- second key componentk3- third key component- Returns:
- the value associated with the multi-key, or
nullif no mapping exists
-
getMultiKey
Optimized 4-key lookup with zero allocation using ThreadLocal array.- Parameters:
k1- first key componentk2- second key componentk3- third key componentk4- fourth key component- Returns:
- the value associated with the multi-key, or
nullif no mapping exists
-
getMultiKey
Optimized 5-key lookup with zero allocation using ThreadLocal array.- Parameters:
k1- first key componentk2- second key componentk3- third key componentk4- fourth key componentk5- fifth key component- Returns:
- the value associated with the multi-key, or
nullif no mapping exists
-
get
Returns the value to which the specified key is mapped, ornullif this map contains no mapping for the key.This method supports both single keys and multidimensional keys. Arrays and Collections are automatically expanded into multi-keys based on the map's configuration settings.
-
putMultiKey
Associates the specified value with the specified multidimensional key using var-args syntax.This is a convenience method that allows easy multi-key storage without having to pass arrays or collections. The keys are treated as separate dimensions of a multi-key.
- Parameters:
value- the value to be associated with the multi-keykeys- the key components for the mapping. Can be null or empty (treated as null key), single key, or multiple key components- Returns:
- the previous value associated with the multi-key, or
nullif there was no mapping for the key - See Also:
-
put
Associates the specified value with the specified key in this map.This method supports both single keys and multidimensional keys. Arrays and Collections are automatically expanded into multi-keys based on the map's configuration settings.
- Specified by:
putin interfaceMap<Object,V> - Parameters:
key- the key with which the specified value is to be associated. Can be a single object, array, or Collection that will be normalized according to the map's settingsvalue- the value to be associated with the specified key- Returns:
- the previous value associated with the key, or
nullif there was no mapping for the key
-
containsMultiKey
Returnstrueif this map contains a mapping for the specified multidimensional key using var-args syntax.This is a convenience method that allows easy multi-key existence checks without having to pass arrays or collections. The keys are treated as separate dimensions of a multi-key.
- Parameters:
keys- the key components to check for. Can be null or empty (treated as null key), single key, or multiple key components- Returns:
trueif this map contains a mapping for the specified multi-key- See Also:
-
containsMultiKey
Optimized 2-key containsKey check with zero allocation using ThreadLocal array.- Parameters:
k1- first key componentk2- second key component- Returns:
trueif this map contains a mapping for the multi-key
-
containsMultiKey
Optimized 3-key containsKey check with zero allocation using ThreadLocal array.- Parameters:
k1- first key componentk2- second key componentk3- third key component- Returns:
trueif this map contains a mapping for the multi-key
-
containsMultiKey
Optimized 4-key containsKey check with zero allocation using ThreadLocal array.- Parameters:
k1- first key componentk2- second key componentk3- third key componentk4- fourth key component- Returns:
trueif this map contains a mapping for the multi-key
-
containsMultiKey
Optimized 5-key containsKey check with zero allocation using ThreadLocal array.- Parameters:
k1- first key componentk2- second key componentk3- third key componentk4- fourth key componentk5- fifth key component- Returns:
trueif this map contains a mapping for the multi-key
-
containsKey
Returnstrueif this map contains a mapping for the specified key.This method supports both single keys and multidimensional keys. Arrays and Collections are automatically expanded into multi-keys based on the map's configuration settings.
- Specified by:
containsKeyin interfaceMap<Object,V> - Parameters:
key- the key whose presence in this map is to be tested. Can be a single object, array, or Collection that will be normalized according to the map's settings- Returns:
trueif this map contains a mapping for the specified key
-
removeMultiKey
Removes the mapping for the specified multidimensional key using var-args syntax.This is a convenience method that allows easy multi-key removal without having to pass arrays or collections. The keys are treated as separate dimensions of a multi-key.
- Parameters:
keys- the key components for the mapping to remove. Can be null or empty (treated as null key), single key, or multiple key components- Returns:
- the previous value associated with the multi-key, or
nullif there was no mapping for the key - See Also:
-
remove
Removes the mapping for the specified key from this map if it is present.This method supports both single keys and multidimensional keys. Arrays and Collections are automatically expanded into multi-keys based on the map's configuration settings.
- Specified by:
removein interfaceMap<Object,V> - Parameters:
key- the key whose mapping is to be removed from the map. Can be a single object, array, or Collection that will be normalized according to the map's settings- Returns:
- the previous value associated with the key, or
nullif there was no mapping for the key
-
size
public int size()Returns the number of key-value mappings in this map.Note: Due to the
Map.size()interface contract requiringint, this method returnsInteger.MAX_VALUEif the actual size exceeds 231-1. For maps that may exceed this limit, uselongSize()to get the accurate count.- Specified by:
sizein interfaceMap<Object,V> - Returns:
- the number of key-value mappings in this map, capped at
Integer.MAX_VALUE - See Also:
-
longSize
public long longSize()Returns the exact number of key-value mappings in this map as along.This method provides the true size without the 231-1 limitation imposed by the
Map.size()contract. Use this method when working with very large maps that may contain more thanInteger.MAX_VALUEentries.- Returns:
- the exact number of key-value mappings in this map
- See Also:
-
isEmpty
public boolean isEmpty()Returnstrueif this map contains no key-value mappings. -
clear
public void clear()Removes all the mappings from this map. The map will be empty after this call returns. -
containsValue
Returnstrueif this map maps one or more keys to the specified value.This operation requires time linear in the map size.
- Specified by:
containsValuein interfaceMap<Object,V> - Parameters:
value- the value whose presence in this map is to be tested- Returns:
trueif this map maps one or more keys to the specified value
-
keySet
Returns aSetview of the keys contained in this map.Multidimensional keys are represented as List (ordered) or Set (unordered), while single keys are returned as their original objects. This provides a consistent mental model: keys are always single items, Lists, or Sets - regardless of nesting depth.
CONTRACT VIOLATION: This method returns a snapshot, not a live view. Changes to the returned set are NOT reflected in the map, and vice versa. This violates the
Map.keySet()contract which requires a live view. -
values
Returns aCollectionview of the values contained in this map.CONTRACT VIOLATION: This method returns a snapshot, not a live view. Changes to the returned collection are NOT reflected in the map, and vice versa. This violates the
Map.values()contract which requires a live view. -
entrySet
Returns aSetview of the mappings contained in this map.Multidimensional keys are represented as List (ordered) or Set (unordered), while single keys are returned as their original objects. This provides a consistent mental model: keys are always single items, Lists, or Sets - regardless of nesting depth.
CONTRACT VIOLATION: This method returns a snapshot, not a live view. Changes to the returned set are NOT reflected in the map, and vice versa. This violates the
Map.entrySet()contract which requires a live view.Rationale: Implementing a true live view would require maintaining bidirectional references between the set and map, adding significant complexity and memory overhead. The snapshot approach provides better performance and thread-safety characteristics for this concurrent data structure, at the cost of contract compliance.
-
putAll
Copies all the mappings from the specified map to this map.The effect of this call is equivalent to that of calling
put(Object, Object)on this map once for each mapping from keykto valuevin the specified map.- Specified by:
putAllin interfaceMap<Object,V> - Parameters:
m- mappings to be stored in this map- Throws:
NullPointerException- if the specified map is null
-
putIfAbsent
If the specified key is not already associated with a value, associates it with the given value.This is equivalent to:
except that the action is performed atomically.if (!map.containsKey(key)) return map.put(key, value); else return map.get(key);- Specified by:
putIfAbsentin interfaceConcurrentMap<Object,V> - Specified by:
putIfAbsentin interfaceMap<Object,V> - Parameters:
key- the key with which the specified value is to be associatedvalue- the value to be associated with the specified key- Returns:
- the previous value associated with the specified key, or
nullif there was no mapping for the key
-
computeIfAbsent
If the specified key is not already associated with a value, attempts to compute its value using the given mapping function and enters it into this map unlessnull.The entire method invocation is performed atomically, so the function is applied at most once per key.
- Specified by:
computeIfAbsentin interfaceConcurrentMap<Object,V> - Specified by:
computeIfAbsentin interfaceMap<Object,V> - Parameters:
key- the key with which the specified value is to be associatedmappingFunction- the function to compute a value- Returns:
- the current (existing or computed) value associated with the specified key,
or
nullif the computed value isnull - Throws:
NullPointerException- if the specified mappingFunction is null
-
computeIfPresent
public V computeIfPresent(Object key, BiFunction<? super Object, ? super V, ? extends V> remappingFunction) If the specified key is not already associated with a value, attempts to compute a new mapping given the key and its current mapped value.The entire method invocation is performed atomically. If the function returns
null, the mapping is removed.- Specified by:
computeIfPresentin interfaceConcurrentMap<Object,V> - Specified by:
computeIfPresentin interfaceMap<Object,V> - Parameters:
key- the key with which the specified value is to be associatedremappingFunction- the function to compute a value- Returns:
- the new value associated with the specified key, or
nullif none - Throws:
NullPointerException- if the specified remappingFunction is null
-
compute
Attempts to compute a mapping for the specified key and its current mapped value (ornullif there is no current mapping).The entire method invocation is performed atomically. If the function returns
null, the mapping is removed (or remains absent if initially absent).- Specified by:
computein interfaceConcurrentMap<Object,V> - Specified by:
computein interfaceMap<Object,V> - Parameters:
key- the key with which the specified value is to be associatedremappingFunction- the function to compute a value- Returns:
- the new value associated with the specified key, or
nullif none - Throws:
NullPointerException- if the specified remappingFunction is null
-
merge
If the specified key is not already associated with a value or is associated with null, associates it with the given non-null value. Otherwise, replaces the associated value with the results of the given remapping function, or removes if the result isnull.The entire method invocation is performed atomically.
- Specified by:
mergein interfaceConcurrentMap<Object,V> - Specified by:
mergein interfaceMap<Object,V> - Parameters:
key- the key with which the resulting value is to be associatedvalue- the non-null value to be merged with the existing valueremappingFunction- the function to recompute a value if present- Returns:
- the new value associated with the specified key, or
nullif no value is associated with the key - Throws:
NullPointerException- if the specified value or remappingFunction is null
-
remove
Removes the entry for a key only if it is currently mapped to the specified value.This is equivalent to:
except that the action is performed atomically.if (map.containsKey(key) && Objects.equals(map.get(key), value)) { map.remove(key); return true; } else return false; -
replace
Replaces the entry for the specified key only if it is currently mapped to some value.This is equivalent to:
except that the action is performed atomically.if (map.containsKey(key)) { return map.put(key, value); } else return null;- Specified by:
replacein interfaceConcurrentMap<Object,V> - Specified by:
replacein interfaceMap<Object,V> - Parameters:
key- the key with which the specified value is to be associatedvalue- the value to be associated with the specified key- Returns:
- the previous value associated with the specified key, or
nullif there was no mapping for the key
-
replace
Replaces the entry for the specified key only if currently mapped to the specified value.This is equivalent to:
except that the action is performed atomically.if (map.containsKey(key) && Objects.equals(map.get(key), oldValue)) { map.put(key, newValue); return true; } else return false;- Specified by:
replacein interfaceConcurrentMap<Object,V> - Specified by:
replacein interfaceMap<Object,V> - Parameters:
key- the key with which the specified value is to be associatedoldValue- the value expected to be associated with the specified keynewValue- the value to be associated with the specified key- Returns:
trueif the value was replaced
-
hashCode
public int hashCode()Returns the hash code value for this map.The hash code of a map is defined to be the sum of the hash codes of each entry in the map's
entrySet()view. This ensures thatm1.equals(m2)implies thatm1.hashCode()==m2.hashCode()for any two mapsm1andm2, as required by the general contract ofObject.hashCode(). -
equals
Compares the specified object with this map for equality.Returns
trueif the given object is also a map and the two maps represent the same mappings. Two mapsm1andm2represent the same mappings ifm1.entrySet().equals(m2.entrySet()). -
toString
Returns a string representation of this map.The string representation consists of a list of key-value mappings in the order returned by the map's entries iterator, enclosed in braces ({}).
Each key-value mapping is rendered as "key → value", where the key part shows all key components and the value part shows the mapped value. Adjacent mappings are separated by commas and newlines.
Empty maps are represented as "{}".
-
reconstructKey
Reconstructs keys as native structures (List, Set, or single items) for serialization. This is the preferred method for entrySet()/keySet() as it returns structures that serialize naturally in JSON without requiring marker parsing.Returns:
- Single item if the key has only one component
- List (ArrayList) for ordered sequences (from OPEN/CLOSE markers or unmarked arrays)
- Set (LinkedHashSet) for unordered sequences (from SET_OPEN/SET_CLOSE markers)
Nested structures are handled recursively, so Lists can contain Sets/Lists/singles, and Sets can contain Lists/Sets/singles. This ensures proper equals/hashCode behavior at all nesting levels.
- Parameters:
in- the flattened internal key array with markers- Returns:
- the reconstructed key using native List/Set/single-item structures
-
printContentionStatistics
public void printContentionStatistics()Prints detailed contention statistics for this map's stripe locking system to the logger.This method outputs comprehensive performance monitoring information including:
- Total lock acquisitions and contentions across all operations
- Global lock statistics (used during resize operations)
- Per-stripe breakdown showing acquisitions, contentions, and contention rates
- Analysis of stripe distribution including most/least contended stripes
- Count of unused stripes for load balancing assessment
This information is useful for performance tuning and understanding concurrency patterns in high-throughput scenarios. The statistics are logged at INFO level.
- See Also:
-
STRIPE_COUNT
-