Class CompactMap<K,V>

java.lang.Object
com.cedarsoftware.util.CompactMap<K,V>
All Implemented Interfaces:
Map<K,V>
Direct Known Subclasses:
CompactCIHashMap, CompactCILinkedMap, CompactLinkedMap

public class CompactMap<K,V> extends Object implements Map<K,V>
A memory-efficient Map implementation that adapts its internal storage structure to minimize memory usage while maintaining excellent performance.

Creating a CompactMap

There are two primary ways to create a CompactMap:

 // Create a case-insensitive, sorted CompactMap
 CompactMap<String, Object> map = CompactMap.<String, Object>builder()
     .caseSensitive(false)
     .sortedOrder()
     .compactSize(80)
     .build();

 // Create a CompactMap with insertion ordering
 CompactMap<String, Object> ordered = CompactMap.<String, Object>builder()
     .insertionOrder()
     .mapType(LinkedHashMap.class)
     .build();
 

Type Inference and Builder Usage

Note the type witness (<String, Object>) in the example above. When using the builder pattern with method chaining, you may need to provide a type witness to help Java's type inference:

 // Alternative approach without type witness
 Builder<String, Object> builder = CompactMap.builder();
 CompactMap<String, Object> map2 = builder
     .caseSensitive(false)
     .sortedOrder()
     .build();
 
The type witness (<String, Object>) is required due to Java's type inference limitations when method chaining directly from the builder() method. If you find the type witness syntax cumbersome, you can split the builder creation and configuration into separate statements as shown in the second example above.

2. Using Constructor


 // Creates a default CompactMap that scales based on size
 CompactMap<String, Object> map = new CompactMap<>();

 // Creates a CompactMap initialized with entries from another map
 CompactMap<String, Object> copy = new CompactMap<>(existingMap);
 
In the examples above, the behavior of the CompactMap will be that of a HashMap, while using the minimal amount of memory possible to hold the contents. The CompactMap has only one instance variable.

Configuration Options

When using the Builder pattern, the following options are available:
MethodDescriptionDefault
caseSensitive(boolean) Controls case sensitivity for string keys true
compactSize(int) Maximum size before switching to backing map 70
mapType(Class) Type of backing map when size exceeds compact size HashMap.class
singleValueKey(K) Special key that enables optimized storage when map contains only one entry with this key "id"
sourceMap(Map) Initializes the CompactMap with entries from the provided map null
sortedOrder() Maintains keys in sorted order unordered
reverseOrder() Maintains keys in reverse order unordered
insertionOrder() Maintains keys in insertion order unordered

Example with Additional Properties


 CompactMap<String, Object> map = CompactMap.builder()
     .caseSensitive(false)
     .sortedOrder()
     .compactSize(80)
     .singleValueKey("uuid")    // Optimize storage for single entry with key "uuid"
     .sourceMap(existingMap)    // Initialize with existing entries
     .build();
 

Internal Storage States

As elements are added to or removed from the map, it transitions through different internal states to optimize memory usage:
State Condition Storage Size Range
Empty val == EMPTY_MAP Sentinel value 0
Single Entry Direct value or Entry Optimized single value storage 1
Compact Array val is Object[] Array with alternating keys/values 2 to compactSize
Backing Map val is Map Standard Map implementation > compactSize

Implementation Note

This class uses runtime optimization techniques to create specialized implementations based on the configuration options. When a CompactMap is first created with a specific combination of options (case sensitivity, ordering, map type, etc.), a custom class is dynamically generated and cached to provide optimal performance for that configuration. This is an implementation detail that is transparent to users of the class.

The generated class names encode the configuration settings. For example:

  • CompactMap$HashMap_CS_S70_id_Unord - A case-sensitive, unordered map with HashMap backing, compact size of 70, and "id" as single value key
  • CompactMap$TreeMap_CI_S100_UUID_Sort - A case-insensitive, sorted map with TreeMap backing, compact size of 100, and "UUID" as single value key
  • CompactMap$LinkedHashMap_CS_S50_Key_Ins - A case-sensitive map with insertion ordering, LinkedHashMap backing, compact size of 50, and "Key" as single value key

For developers interested in the internal mechanics, the source code contains detailed documentation of the template generation and compilation process.

Note: As elements are removed, the map will transition back through these states in reverse order to maintain optimal memory usage.

While subclassing CompactMap is still supported for backward compatibility, it is recommended to use the Builder pattern for new implementations.

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.
  • Field Details

  • Constructor Details

    • CompactMap

      public CompactMap()
      Constructs an empty CompactMap with the default configuration.

      This constructor ensures that the `compactSize()` method returns a value greater than or equal to 2.

      Throws:
      IllegalStateException - if compactSize() returns a value less than 2
    • CompactMap

      public CompactMap(Map<K,V> other)
      Constructs a CompactMap initialized with the entries from the provided map.

      The entries are copied from the provided map, and the internal representation is determined based on the number of entries and the compactSize() threshold.

      Parameters:
      other - the map whose entries are to be placed in this map
      Throws:
      NullPointerException - if other is null
  • Method Details

    • size

      public int size()
      Returns the number of key-value mappings in this map.

      If the map contains more than Integer.MAX_VALUE elements, returns Integer.MAX_VALUE.

      Specified by:
      size in interface Map<K,V>
      Returns:
      the number of key-value mappings in this map
    • isEmpty

      public boolean isEmpty()
      Specified by:
      isEmpty in interface Map<K,V>
      Returns:
      true if this map contains no key-value mappings; false otherwise
    • containsKey

      public boolean containsKey(Object key)
      Returns true if this map contains a mapping for the specified key.
      Specified by:
      containsKey in interface Map<K,V>
      Parameters:
      key - the key whose presence in this map is to be tested
      Returns:
      true if this map contains a mapping for the specified key; false otherwise
    • containsValue

      public boolean containsValue(Object value)
      Returns true if this map maps one or more keys to the specified value.
      Specified by:
      containsValue in interface Map<K,V>
      Parameters:
      value - the value whose presence in this map is to be tested
      Returns:
      true if this map maps one or more keys to the specified value; false otherwise
    • get

      public V get(Object key)
      Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.

      A return value of null does not necessarily indicate that the map contains no mapping for the key; it is also possible that the map explicitly maps the key to null.

      Specified by:
      get in interface Map<K,V>
      Parameters:
      key - the key whose associated value is to be returned
      Returns:
      the value to which the specified key is mapped, or null if this map contains no mapping for the key
    • put

      public V put(K key, V value)
      Associates the specified value with the specified key in this map. If the map previously contained a mapping for the key, the old value is replaced.
      Specified by:
      put in interface Map<K,V>
      Parameters:
      key - key with which the specified value is to be associated
      value - value to be associated with the specified key
      Returns:
      the previous value associated with key, or null if there was no mapping for key.
      Throws:
      NullPointerException - if the specified key is null and this map does not permit null keys
      ClassCastException - if the key is of an inappropriate type for this map
    • remove

      public V remove(Object key)
      Removes the mapping for the specified key from this map if present.
      Specified by:
      remove in interface Map<K,V>
    • putAll

      public void putAll(Map<? extends K,? extends V> map)
      Copies all mappings from the specified map into this map.

      If resulting size would exceed compactSize, transitions directly to map storage. Otherwise, adds entries individually, allowing natural transitions to occur.

      Specified by:
      putAll in interface Map<K,V>
      Parameters:
      map - mappings to be stored in this map
      Throws:
      NullPointerException - if the specified map is null
    • clear

      public void clear()
      Removes all mappings from this map.

      Resets internal storage to empty state, allowing garbage collection of any existing storage structures.

      Specified by:
      clear in interface Map<K,V>
    • hashCode

      public int hashCode()
      Returns the hash code value for this map.

      The hash code of a map is defined as the sum of the hash codes of each entry in the map's entry set. This implementation ensures consistency with the `equals` method.

      Specified by:
      hashCode in interface Map<K,V>
      Overrides:
      hashCode in class Object
      Returns:
      the hash code value for this map
    • equals

      public boolean equals(Object obj)
      Compares the specified object with this map for equality.

      Returns true if the given object is also a map and the two maps represent the same mappings. More formally, two maps m1 and m2 are equal if:

      
       m1.entrySet().equals(m2.entrySet())
       
      Specified by:
      equals in interface Map<K,V>
      Overrides:
      equals in class Object
      Parameters:
      obj - the object to be compared for equality with this map
      Returns:
      true if the specified object is equal to this map
    • toString

      public String 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 entrySet iterator, enclosed in braces ("{}"). Adjacent mappings are separated by the characters ", " (comma and space). Each key-value mapping is rendered as the key followed by an equals sign ("=") followed by the associated value.

      Overrides:
      toString in class Object
      Returns:
      a string representation of this map
    • keySet

      public Set<K> keySet()
      Returns a Set view of the keys in this map.

      The set is backed by the map, so changes to the map are reflected in the set. Set supports element removal but not addition. Iterator supports concurrent modification detection.

      Specified by:
      keySet in interface Map<K,V>
      Returns:
      a set view of the keys contained in this map
    • values

      public Collection<V> values()
      Returns a Collection view of the values contained in this map.

      The collection is backed by the map, so changes to the map are reflected in the collection, and vice versa. If the map is modified while an iteration over the collection is in progress (except through the iterators own remove operation), the results of the iteration are undefined. The collection supports element removal, which removes the corresponding mapping from the map. It does not support the add or addAll operations.

      Specified by:
      values in interface Map<K,V>
      Returns:
      a collection view of the values contained in this map
    • entrySet

      public Set<Map.Entry<K,V>> entrySet()
      Returns a Set view of the mappings contained in this map.

      Each element in the returned set is a Map.Entry. The set is backed by the map, so changes to the map are reflected in the set, and vice versa. If the map is modified while an iteration over the set is in progress (except through the iterators own remove operation, or through the setValue operation on a map entry returned by the iterator), the results of the iteration are undefined. The set supports element removal, which removes the corresponding mapping from the map. It does not support the add or addAll operations.

      Specified by:
      entrySet in interface Map<K,V>
      Returns:
      a set view of the mappings contained in this map
    • minus

      @Deprecated public Map<K,V> minus(Object removeMe)
      Deprecated.
    • plus

      @Deprecated public Map<K,V> plus(Object right)
      Deprecated.
    • getLogicalValueType

      protected CompactMap.LogicalValueType getLogicalValueType()
      Returns the current storage state of this map.

      Possible states are: EMPTY (no entries), OBJECT (single value), ENTRY (single entry), MAP (backing map), or ARRAY (compact array storage). Used internally to determine appropriate operations for current state.

      Returns:
      the LogicalValueType enum representing current storage state
    • computeKeyHashCode

      protected int computeKeyHashCode(Object key)
      Computes hash code for map keys, handling special cases.

      For String keys, respects case sensitivity setting. Handles null keys, self-referential keys, and standard objects. Used for both map operations and entry hash codes.

      Parameters:
      key - the key to compute hash code for
      Returns:
      the computed hash code for the key
    • computeValueHashCode

      protected int computeValueHashCode(Object value)
      Computes hash code for map values, handling special cases.

      Handles null values and self-referential values (where value is this map). Used for both map operations and entry hash codes.

      Parameters:
      value - the value to compute hash code for
      Returns:
      the computed hash code for the value
    • getSingleValueKey

      protected K getSingleValueKey()
      Returns the designated key for optimized single-value storage.

      When map contains one entry with this key, value is stored directly. Default implementation returns "id". Override to customize.

      Returns:
      the key to use for optimized single-value storage
    • getNewMap

      protected Map<K,V> getNewMap()
      Creates the backing map instance when size exceeds compactSize.

      Default implementation returns HashMap. Override to provide different map implementation (e.g., TreeMap for sorted maps, LinkedHashMap for insertion ordered maps).

      Returns:
      new empty map instance for backing storage
    • isCaseInsensitive

      protected boolean isCaseInsensitive()
      Determines if String keys are compared case-insensitively.

      Default implementation returns false (case-sensitive). Override to change String key comparison behavior. Affects key equality and sorting.

      Returns:
      true if String keys should be compared ignoring case, false otherwise
    • compactSize

      protected int compactSize()
      Returns the threshold size for compact array storage.

      When size exceeds this value, switches to map storage. When size reduces to this value, returns to array storage. Default implementation returns 70.

      Returns:
      the maximum number of entries for compact array storage
    • getOrdering

      protected String getOrdering()
      Returns the ordering strategy for this map.

      Valid values include:

      Returns:
      the ordering strategy for this map
    • builder

      public static <K, V> CompactMap.Builder<K,V> builder()
      Returns a builder for creating customized CompactMap instances.

      For detailed configuration options and examples, see CompactMap.Builder.

      Note: When method chaining directly from builder(), you may need to provide a type witness to help type inference:

      
       // Type witness needed:
       CompactMap<String, Integer> map = CompactMap.<String, Integer>builder()
               .sortedOrder()
               .build();
      
       // Alternative without type witness:
       Builder<String, Integer> builder = CompactMap.builder();
       CompactMap<String, Integer> map = builder.sortedOrder().build();
       
      Type Parameters:
      K - the type of keys maintained by the map
      V - the type of mapped values
      Returns:
      a new CompactMapBuilder instance
      See Also: