Class ClassValueMap<V>
- Type Parameters:
V- the type of mapped values
- All Implemented Interfaces:
ConcurrentMap<Class<?>,,V> Map<Class<?>,V>
Performance Advantages
ClassValueMap provides significantly faster get() operations compared to standard
Map implementations:
- 2-10x faster than HashMap for key lookups
- 3-15x faster than ConcurrentHashMap for concurrent access patterns
- The performance advantage increases with contention (multiple threads)
- Most significant when looking up the same class keys repeatedly
How It Works
The implementation utilizes Java's ClassValue mechanism, which is specially optimized
in the JVM through:
- Thread-local caching for reduced contention
- Identity-based lookups (faster than equality checks)
- Special VM support that connects directly to Class metadata structures
- Optimized memory layout that can reduce cache misses
Drop-in Replacement
ClassValueMap is designed as a drop-in replacement for existing maps with Class keys:
- Fully implements the
MapandConcurrentMapinterfaces - Supports all standard map operations (put, remove, clear, etc.)
- Handles null keys and null values just like standard map implementations
- Thread-safe for all operations
Ideal Use Cases
ClassValueMap is ideal for:
- High read-to-write ratio scenarios (read-mostly workloads)
- Caches for class-specific handlers, factories, or metadata
- Performance-critical operations in hot code paths
- Type registries in frameworks (serializers, converters, validators)
- Class capability or feature mappings
- Any system that frequently maps from Class objects to associated data
Trade-offs
The performance benefits come with some trade-offs:
- Higher memory usage (maintains both a backing map and ClassValue cache)
- Write operations (put/remove) aren't faster and may be slightly slower
- Only Class keys benefit from the optimized lookups
Thread Safety
This implementation is thread-safe for all operations and implements ConcurrentMap.
Usage Example
// Create a registry of class handlers
ClassValueMap<Handler> handlerRegistry = new ClassValueMap<>();
handlerRegistry.put(String.class, new StringHandler());
handlerRegistry.put(Integer.class, new IntegerHandler());
handlerRegistry.put(List.class, new ListHandler());
// Fast lookup in a performance-critical context
public void process(Object obj) {
Handler handler = handlerRegistry.get(obj.getClass());
if (handler != null) {
handler.handle(obj);
} else {
// Default handling
}
}
Important Performance Warning
Wrapping this class with standard collection wrappers like Collections.unmodifiableMap()
or Collections.newSetFromMap() will destroy the ClassValue performance benefits.
Always use the raw ClassValueMap directly or use the provided unmodifiableView() method
if immutability is required.
- 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. - See Also:
-
Nested Class Summary
Nested classes/interfaces inherited from class java.util.AbstractMap
AbstractMap.SimpleEntry<K extends Object,V extends Object>, AbstractMap.SimpleImmutableEntry<K extends Object, V extends Object> -
Constructor Summary
ConstructorsConstructorDescriptionCreates a ClassValueMapClassValueMap(Map<? extends Class<?>, ? extends V> map) Creates a ClassValueMap containing the mappings from the specified map. -
Method Summary
Modifier and TypeMethodDescriptionvoidclear()computeIfAbsent(Class<?> key, Function<? super Class<?>, ? extends V> mappingFunction) booleancontainsKey(Object key) booleancontainsValue(Object value) entrySet()voidforEach(BiConsumer<? super Class<?>, ? super V> action) booleanisEmpty()putIfAbsent(Class<?> key, V value) booleanbooleanintsize()Returns an unmodifiable view of this map that preserves ClassValue performance benefits.values()Methods inherited from class java.util.AbstractMap
clone, equals, hashCode, keySet, putAll, toStringMethods inherited from class java.lang.Object
finalize, getClass, notify, notifyAll, wait, wait, waitMethods inherited from interface java.util.concurrent.ConcurrentMap
computeIfPresent, getOrDefault, merge, replaceAll
-
Constructor Details
-
ClassValueMap
public ClassValueMap()Creates a ClassValueMap -
ClassValueMap
Creates a ClassValueMap containing the mappings from the specified map.- Parameters:
map- the map whose mappings are to be placed in this map- Throws:
NullPointerException- if the specified map is null
-
-
Method Details
-
get
-
put
-
remove
-
containsKey
- Specified by:
containsKeyin interfaceMap<Class<?>,V> - Overrides:
containsKeyin classAbstractMap<Class<?>,V>
-
clear
public void clear() -
size
public int size() -
isEmpty
public boolean isEmpty() -
containsValue
- Specified by:
containsValuein interfaceMap<Class<?>,V> - Overrides:
containsValuein classAbstractMap<Class<?>,V>
-
forEach
-
entrySet
-
putIfAbsent
- Specified by:
putIfAbsentin interfaceConcurrentMap<Class<?>,V> - Specified by:
putIfAbsentin interfaceMap<Class<?>,V>
-
computeIfAbsent
Overridden to correctly handle null-value mappings. The default ConcurrentMap implementation cannot distinguish between "key absent" and "key maps to null" (both return null from get()), causing the computed value to be returned without actually being stored when a null-value mapping exists.
- Specified by:
computeIfAbsentin interfaceConcurrentMap<Class<?>,V> - Specified by:
computeIfAbsentin interfaceMap<Class<?>,V>
-
compute
public V compute(Class<?> key, BiFunction<? super Class<?>, ? super V, ? extends V> remappingFunction) Overridden to correctly handle null-value mappings. The default ConcurrentMap implementation uses
putIfAbsent()whenget()returns null, butputIfAbsent()returns null for both "inserted successfully" and "existing value is null," causing incorrect behavior. -
remove
-
replace
-
replace
-
values
-
unmodifiableView
Returns an unmodifiable view of this map that preserves ClassValue performance benefits. Unlike Collections.unmodifiableMap(), this method returns a view that maintains the fast lookup performance for Class keys.- Returns:
- an unmodifiable view of this map with preserved performance characteristics
-