Class UnmodifiableArrayBackedMap

  • All Implemented Interfaces:
    java.io.Serializable, java.util.Map<java.lang.String,​java.lang.String>, ReadOnlyStringMap

    public class UnmodifiableArrayBackedMap
    extends java.util.AbstractMap<java.lang.String,​java.lang.String>
    implements ReadOnlyStringMap
    This class represents an immutable map, which stores its state inside a single Object[]:
    1. [0] contains the number of entries
    2. Others contain alternating key-value pairs, for example [1]="1" and [2]="value_for_1"
    Keys are calculated using (index * 2 + 1) and values are (index * 2 + 2). Performance:
    • Implements very low-cost copies: shallow-copy the array.
    • Doesn't matter for mutable operations, since we don't allow them.
    • Iterates very quickly, since it iterates directly across the array. This contrasts with HashMap's requirement to scan each bucket in the table and chase each pointer.
    • Is linear on gets, puts, and removes, since the table must be scanned to find a matching key.
    Allocation:
    • Zero on reads.
    • Copy-and-modify operations allocate exactly two objects: the new array and the new Map instance. This is substantially better than HashMap, which requires a new Node for each entry.
    See Also:
    Serialized Form
    • Nested Class Summary

      Nested Classes 
      Modifier and Type Class Description
      private class  UnmodifiableArrayBackedMap.UnmodifiableEntry
      Implementation of Map.Entry.
      private class  UnmodifiableArrayBackedMap.UnmodifiableEntryIterator
      Simple Entry iterator, tracking solely the index in the array.
      private class  UnmodifiableArrayBackedMap.UnmodifiableEntrySet
      Simple Entry set, providing a reference to UnmodifiableEntryIterator and blocking modifications.
      • Nested classes/interfaces inherited from class java.util.AbstractMap

        java.util.AbstractMap.SimpleEntry<K extends java.lang.Object,​V extends java.lang.Object>, java.util.AbstractMap.SimpleImmutableEntry<K extends java.lang.Object,​V extends java.lang.Object>
      • Nested classes/interfaces inherited from interface java.util.Map

        java.util.Map.Entry<K extends java.lang.Object,​V extends java.lang.Object>
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      private void add​(java.lang.String key, java.lang.String value)  
      private void addOrOverwriteKey​(java.lang.String key, java.lang.String value)
      Find an existing entry (if any) and overwrites the value, if found
      void clear()  
      boolean containsKey​(java.lang.Object key)
      Scans the array to find a matching key.
      boolean containsKey​(java.lang.String key)
      Returns true if this data structure contains the specified key, false otherwise.
      boolean containsValue​(java.lang.Object value)
      Scans the array to find a matching value, with linear time.
      UnmodifiableArrayBackedMap copyAndPut​(java.lang.String key, java.lang.String value)
      Creates a new instance that contains the same entries as this map, plus either the new entry or updated value passed in the parameters.
      UnmodifiableArrayBackedMap copyAndPutAll​(java.util.Map<java.lang.String,​java.lang.String> entriesToAdd)
      Creates a new instance that contains the same entries as this map, plus the new entries or updated values passed in the parameters.
      UnmodifiableArrayBackedMap copyAndRemove​(java.lang.String key)
      Creates a new instance that contains the same entries as this map, minus the entry with the specified key (if such an entry exists).
      UnmodifiableArrayBackedMap copyAndRemoveAll​(java.lang.Iterable<java.lang.String> keysToRemoveIterable)
      Creates a new instance where the entries of provided keys are removed.
      java.util.Set<java.util.Map.Entry<java.lang.String,​java.lang.String>> entrySet()  
      void forEach​(java.util.function.BiConsumer<? super java.lang.String,​? super java.lang.String> action)
      This version of forEach is defined on the Map interface.
      <V> void forEach​(BiConsumer<java.lang.String,​? super V> action)
      This version of forEach is defined on the ReadOnlyStringMap interface.
      <V,​S>
      void
      forEach​(TriConsumer<java.lang.String,​? super V,​S> action, S state)
      Performs the given action for each key-value pair in this data structure until all entries have been processed or the action throws an exception.
      java.lang.String get​(java.lang.Object key)
      Scans the array to find a matching key.
      private static int getArrayIndexForKey​(int entryIndex)  
      private static int getArrayIndexForValue​(int entryIndex)  
      java.lang.Object[] getBackingArray()  
      static UnmodifiableArrayBackedMap getMap​(java.lang.Object[] backingArray)  
      <V> V getValue​(java.lang.String key)
      Returns the value for the specified key, or null if the specified key does not exist in this collection.
      java.lang.String put​(java.lang.String key, java.lang.String value)  
      void putAll​(java.util.Map<? extends java.lang.String,​? extends java.lang.String> m)  
      java.lang.String remove​(java.lang.Object key)  
      int size()
      Returns the number of key-value pairs in this collection.
      java.util.Map<java.lang.String,​java.lang.String> toMap()
      Returns a non-null mutable Map<String, String> containing a snapshot of this data structure.
      private void updateNumEntriesInArray()
      Copies the locally-tracked numEntries into the first array slot.
      • Methods inherited from class java.util.AbstractMap

        clone, equals, hashCode, isEmpty, keySet, toString, values
      • Methods inherited from class java.lang.Object

        finalize, getClass, notify, notifyAll, wait, wait, wait
      • Methods inherited from interface java.util.Map

        compute, computeIfAbsent, computeIfPresent, getOrDefault, merge, putIfAbsent, remove, replace, replace, replaceAll
    • Field Detail

      • NUM_FIXED_ARRAY_ENTRIES

        private static final int NUM_FIXED_ARRAY_ENTRIES
        See Also:
        Constant Field Values
      • backingArray

        private java.lang.Object[] backingArray
        backingArray is functionally final, but marking it as such can cause performance problems. Consider marking it final after https://bugs.openjdk.org/browse/JDK-8324186 is solved.
      • numEntries

        private int numEntries
    • Constructor Detail

      • UnmodifiableArrayBackedMap

        private UnmodifiableArrayBackedMap​(int capacity)
      • UnmodifiableArrayBackedMap

        private UnmodifiableArrayBackedMap​(java.lang.Object[] backingArray)
    • Method Detail

      • getArrayIndexForKey

        private static int getArrayIndexForKey​(int entryIndex)
      • getArrayIndexForValue

        private static int getArrayIndexForValue​(int entryIndex)
      • add

        private void add​(java.lang.String key,
                         java.lang.String value)
      • clear

        public void clear()
        Specified by:
        clear in interface java.util.Map<java.lang.String,​java.lang.String>
        Overrides:
        clear in class java.util.AbstractMap<java.lang.String,​java.lang.String>
      • containsKey

        public boolean containsKey​(java.lang.Object key)
        Scans the array to find a matching key. Linear performance.
        Specified by:
        containsKey in interface java.util.Map<java.lang.String,​java.lang.String>
        Overrides:
        containsKey in class java.util.AbstractMap<java.lang.String,​java.lang.String>
      • containsKey

        public boolean containsKey​(java.lang.String key)
        Description copied from interface: ReadOnlyStringMap
        Returns true if this data structure contains the specified key, false otherwise.
        Specified by:
        containsKey in interface ReadOnlyStringMap
        Parameters:
        key - the key whose presence to check. May be null.
        Returns:
        true if this data structure contains the specified key, false otherwise.
      • getBackingArray

        public java.lang.Object[] getBackingArray()
      • containsValue

        public boolean containsValue​(java.lang.Object value)
        Scans the array to find a matching value, with linear time. Allows null parameter.
        Specified by:
        containsValue in interface java.util.Map<java.lang.String,​java.lang.String>
        Overrides:
        containsValue in class java.util.AbstractMap<java.lang.String,​java.lang.String>
      • copyAndPut

        public UnmodifiableArrayBackedMap copyAndPut​(java.lang.String key,
                                                     java.lang.String value)
        Creates a new instance that contains the same entries as this map, plus either the new entry or updated value passed in the parameters.
        Parameters:
        key -
        value -
        Returns:
      • copyAndPutAll

        public UnmodifiableArrayBackedMap copyAndPutAll​(java.util.Map<java.lang.String,​java.lang.String> entriesToAdd)
        Creates a new instance that contains the same entries as this map, plus the new entries or updated values passed in the parameters.
      • copyAndRemove

        public UnmodifiableArrayBackedMap copyAndRemove​(java.lang.String key)
        Creates a new instance that contains the same entries as this map, minus the entry with the specified key (if such an entry exists).
      • copyAndRemoveAll

        public UnmodifiableArrayBackedMap copyAndRemoveAll​(java.lang.Iterable<java.lang.String> keysToRemoveIterable)
        Creates a new instance where the entries of provided keys are removed.
      • updateNumEntriesInArray

        private void updateNumEntriesInArray()
        Copies the locally-tracked numEntries into the first array slot. Requires autoboxing so call should be minimized - for example, once per bulk update operation.
      • forEach

        public void forEach​(java.util.function.BiConsumer<? super java.lang.String,​? super java.lang.String> action)
        This version of forEach is defined on the Map interface.
        Specified by:
        forEach in interface java.util.Map<java.lang.String,​java.lang.String>
      • forEach

        public <V> void forEach​(BiConsumer<java.lang.String,​? super V> action)
        This version of forEach is defined on the ReadOnlyStringMap interface.
        Specified by:
        forEach in interface ReadOnlyStringMap
        Type Parameters:
        V - type of the value.
        Parameters:
        action - The action to be performed for each key-value pair in this collection.
      • forEach

        public <V,​S> void forEach​(TriConsumer<java.lang.String,​? super V,​S> action,
                                        S state)
        Description copied from interface: ReadOnlyStringMap
        Performs the given action for each key-value pair in this data structure until all entries have been processed or the action throws an exception.

        The third parameter lets callers pass in a stateful object to be modified with the key-value pairs, so the TriConsumer implementation itself can be stateless and potentially reusable.

        Some implementations may not support structural modifications (adding new elements or removing elements) while iterating over the contents. In such implementations, attempts to add or remove elements from the TriConsumer's accept method may cause a ConcurrentModificationException to be thrown.

        Specified by:
        forEach in interface ReadOnlyStringMap
        Type Parameters:
        V - type of the value.
        S - type of the third parameter.
        Parameters:
        action - The action to be performed for each key-value pair in this collection.
        state - the object to be passed as the third parameter to each invocation on the specified triconsumer.
      • entrySet

        public java.util.Set<java.util.Map.Entry<java.lang.String,​java.lang.String>> entrySet()
        Specified by:
        entrySet in interface java.util.Map<java.lang.String,​java.lang.String>
        Specified by:
        entrySet in class java.util.AbstractMap<java.lang.String,​java.lang.String>
      • get

        public java.lang.String get​(java.lang.Object key)
        Scans the array to find a matching key. Linear-time.
        Specified by:
        get in interface java.util.Map<java.lang.String,​java.lang.String>
        Overrides:
        get in class java.util.AbstractMap<java.lang.String,​java.lang.String>
      • getValue

        public <V> V getValue​(java.lang.String key)
        Description copied from interface: ReadOnlyStringMap
        Returns the value for the specified key, or null if the specified key does not exist in this collection.
        Specified by:
        getValue in interface ReadOnlyStringMap
        Parameters:
        key - the key whose value to return.
        Returns:
        the value for the specified key or null.
      • addOrOverwriteKey

        private void addOrOverwriteKey​(java.lang.String key,
                                       java.lang.String value)
        Find an existing entry (if any) and overwrites the value, if found
        Parameters:
        key -
        value -
      • put

        public java.lang.String put​(java.lang.String key,
                                    java.lang.String value)
        Specified by:
        put in interface java.util.Map<java.lang.String,​java.lang.String>
        Overrides:
        put in class java.util.AbstractMap<java.lang.String,​java.lang.String>
      • putAll

        public void putAll​(java.util.Map<? extends java.lang.String,​? extends java.lang.String> m)
        Specified by:
        putAll in interface java.util.Map<java.lang.String,​java.lang.String>
        Overrides:
        putAll in class java.util.AbstractMap<java.lang.String,​java.lang.String>
      • remove

        public java.lang.String remove​(java.lang.Object key)
        Specified by:
        remove in interface java.util.Map<java.lang.String,​java.lang.String>
        Overrides:
        remove in class java.util.AbstractMap<java.lang.String,​java.lang.String>
      • size

        public int size()
        Description copied from interface: ReadOnlyStringMap
        Returns the number of key-value pairs in this collection.
        Specified by:
        size in interface java.util.Map<java.lang.String,​java.lang.String>
        Specified by:
        size in interface ReadOnlyStringMap
        Overrides:
        size in class java.util.AbstractMap<java.lang.String,​java.lang.String>
        Returns:
        the number of key-value pairs in this collection.
      • toMap

        public java.util.Map<java.lang.String,​java.lang.String> toMap()
        Description copied from interface: ReadOnlyStringMap
        Returns a non-null mutable Map<String, String> containing a snapshot of this data structure.
        Specified by:
        toMap in interface ReadOnlyStringMap
        Returns:
        a mutable copy of this data structure in Map<String, String> form.