Class IdentityObjectMap<K,V>

java.lang.Object
com.github.tommyettinger.ds.ObjectObjectMap<K,V>
com.github.tommyettinger.ds.IdentityObjectMap<K,V>
All Implemented Interfaces:
Iterable<Map.Entry<K,V>>, Map<K,V>

public class IdentityObjectMap<K,V> extends ObjectObjectMap<K,V>
A variant on ObjectObjectMap that compares keys by identity (using ==) instead of equality (using equals()). It also hashes with System.identityHashCode(Object) instead of calling the hashCode() of a key. This can be useful in some cases where keys may have invalid Object.equals(Object) and/or Object.hashCode() implementations, or if keys could be very large (making a hashCode() that uses all the items in the key slow). Oddly, System.identityHashCode(Object) tends to be slower than the hashCode() for most small keys, because an explicitly-written hashCode() typically doesn't need to do anything concurrently, but identityHashCode() needs to (concurrently) modify an internal JVM variable that ensures the results are unique, and that requires the JVM to do lots of extra work whenever identityHashCode() is called. Despite that, identityHashCode() doesn't depend on the quantity of variables in the key, so identityHashCode() gets relatively faster for larger keys. The equals() method used by ObjectObjectMap also tends to slow down for large keys, relative to the constant-time == this uses.
Note that the ObjectObjectMap.entrySet(), ObjectObjectMap.keySet() and individual Entry items this produces are those of an ObjectObjectMap, and so do not compare by identity.
  • Constructor Details

    • IdentityObjectMap

      public IdentityObjectMap()
      Creates a new map with an initial capacity of Utilities.getDefaultTableCapacity() and a load factor of Utilities.getDefaultLoadFactor().
    • IdentityObjectMap

      public IdentityObjectMap(int initialCapacity)
      Creates a new map with the given starting capacity and a load factor of Utilities.getDefaultLoadFactor().
      Parameters:
      initialCapacity - If not a power of two, it is increased to the next nearest power of two.
    • IdentityObjectMap

      public IdentityObjectMap(int initialCapacity, float loadFactor)
      Creates a new map with the specified initial capacity and load factor. This map will hold initialCapacity items before growing the backing table.
      Parameters:
      initialCapacity - If not a power of two, it is increased to the next nearest power of two.
      loadFactor - what fraction of the capacity can be filled before this has to resize; 0 < loadFactor <= 1
    • IdentityObjectMap

      public IdentityObjectMap(ObjectObjectMap<? extends K,? extends V> map)
      Creates a new map identical to the specified map.
      Parameters:
      map - an ObjectObjectMap to copy, or a subclass such as this one
    • IdentityObjectMap

      public IdentityObjectMap(Map<? extends K,? extends V> map)
      Creates a new map identical to the specified map.
      Parameters:
      map - a Map to copy
    • IdentityObjectMap

      public IdentityObjectMap(K[] keys, V[] values)
      Given two side-by-side arrays, one of keys, one of values, this constructs a map and inserts each pair of key and value into it. If keys and values have different lengths, this only uses the length of the smaller array.
      Parameters:
      keys - an array of keys
      values - an array of values
    • IdentityObjectMap

      public IdentityObjectMap(Collection<? extends K> keys, Collection<? extends V> values)
      Given two side-by-side collections, one of keys, one of values, this constructs a map and inserts each pair of key and value into it. If keys and values have different lengths, this only uses the length of the smaller collection.
      Parameters:
      keys - a Collection of keys
      values - a Collection of values
  • Method Details

    • place

      protected int place(Object item)
      Returns an index >= 0 and <= ObjectObjectMap.mask for the specified item.

      This particular overload relies on the naturally-random nature of System.identityHashCode(Object), and just masks the identity hash code so only the lower bits are used. This should be fine because the identity hash code defaults to a decent random number generator for its output, so it should collide over all bits very rarely, and collide only over the masked bits somewhat rarely.

      Overrides:
      place in class ObjectObjectMap<K,V>
      Parameters:
      item - a non-null Object; its identityHashCode is used here
      Returns:
      an index between 0 and ObjectObjectMap.mask (both inclusive)
    • equate

      protected boolean equate(Object left, Object right)
      Description copied from class: ObjectObjectMap
      Compares the objects left and right, which are usually keys, for equality, returning true if they are considered equal. This is used by the rest of this class to determine whether two keys are considered equal. Normally, this returns left.equals(right), but subclasses can override it to use reference equality, fuzzy equality, deep array equality, or any other custom definition of equality. Usually, ObjectObjectMap.place(Object) is also overridden if this method is.
      Overrides:
      equate in class ObjectObjectMap<K,V>
      Parameters:
      left - must be non-null; typically a key being compared, but not necessarily
      right - may be null; typically a key being compared, but can often be null for an empty key slot, or some other type
      Returns:
      true if left and right are considered equal for the purposes of this class
    • hashCode

      public int hashCode()
      Specified by:
      hashCode in interface Map<K,V>
      Overrides:
      hashCode in class ObjectObjectMap<K,V>
    • getHashMultiplier

      public int getHashMultiplier()
      Effectively does nothing here because the hashMultiplier is not used by identity hashing.
      Overrides:
      getHashMultiplier in class ObjectObjectMap<K,V>
      Returns:
      any int; the value isn't used internally, but may be used by subclasses to identify something
    • setHashMultiplier

      public void setHashMultiplier(int hashMultiplier)
      Effectively does nothing here because the hashMultiplier is not used by identity hashing. Subclasses can use this to set some kind of identifier or user data, though. Unlike the superclass implementation, this does not alter the given int to make it negative or odd.
      Overrides:
      setHashMultiplier in class ObjectObjectMap<K,V>
      Parameters:
      hashMultiplier - any int; will not be used
    • with

      public static <K, V> IdentityObjectMap<K,V> with()
      Constructs an empty map given the types as generic type arguments. This is usually less useful than just using the constructor, but can be handy in some code-generation scenarios when you don't know how many arguments you will have.
      Type Parameters:
      K - the type of keys
      V - the type of values
      Returns:
      a new map containing nothing
    • with

      public static <K, V> IdentityObjectMap<K,V> with(K key0, V value0)
      Constructs a single-entry map given one key and one value. This is mostly useful as an optimization for with(Object, Object, Object...) when there's no "rest" of the keys or values.
      Type Parameters:
      K - the type of key0
      V - the type of value0
      Parameters:
      key0 - the first and only key
      value0 - the first and only value
      Returns:
      a new map containing just the entry mapping key0 to value0
    • with

      public static <K, V> IdentityObjectMap<K,V> with(K key0, V value0, Object... rest)
      Constructs a map given alternating keys and values. This can be useful in some code-generation scenarios, or when you want to make a map conveniently by-hand and have it populated at the start. You can also use IdentityObjectMap(Object[], Object[]), which takes all keys and then all values. This needs all keys to have the same type and all values to have the same type, because it gets those types from the first key parameter and first value parameter. Any keys that don't have K as their type or values that don't have V as their type have that entry skipped.
      Type Parameters:
      K - the type of keys, inferred from key0
      V - the type of values, inferred from value0
      Parameters:
      key0 - the first key; will be used to determine the type of all keys
      value0 - the first value; will be used to determine the type of all values
      rest - an array or varargs of alternating K, V, K, V... elements
      Returns:
      a new map containing the given keys and values
    • parse

      public static <K, V> IdentityObjectMap<K,V> parse(String str, String entrySeparator, String keyValueSeparator, PartialParser<K> keyParser, PartialParser<V> valueParser)
      Creates a new map by parsing all of str with the given PartialParser for keys and for values, with entries separated by entrySeparator, such as ", " and the keys separated from values by keyValueSeparator, such as "=".
      Various PartialParser instances are defined as constants, such as PartialParser.DEFAULT_STRING, and others can be created by static methods in PartialParser, such as PartialParser.objectListParser(PartialParser, String, boolean).
      Parameters:
      str - a String containing parseable text
      entrySeparator - the String separating every key-value pair
      keyValueSeparator - the String separating every key from its corresponding value
      keyParser - a PartialParser that returns a K key from a section of str
      valueParser - a PartialParser that returns a V value from a section of str
    • parse

      public static <K, V> IdentityObjectMap<K,V> parse(String str, String entrySeparator, String keyValueSeparator, PartialParser<K> keyParser, PartialParser<V> valueParser, boolean brackets)
      Creates a new map by parsing all of str (or if brackets is true, all but the first and last chars) with the given PartialParser for keys and for values, with entries separated by entrySeparator, such as ", " and the keys separated from values by keyValueSeparator, such as "=".
      Various PartialParser instances are defined as constants, such as PartialParser.DEFAULT_STRING, and others can be created by static methods in PartialParser, such as PartialParser.objectListParser(PartialParser, String, boolean).
      Parameters:
      str - a String containing parseable text
      entrySeparator - the String separating every key-value pair
      keyValueSeparator - the String separating every key from its corresponding value
      keyParser - a PartialParser that returns a K key from a section of str
      valueParser - a PartialParser that returns a V value from a section of str
      brackets - if true, the first and last chars in str will be ignored
    • parse

      public static <K, V> IdentityObjectMap<K,V> parse(String str, String entrySeparator, String keyValueSeparator, PartialParser<K> keyParser, PartialParser<V> valueParser, int offset, int length)
      Creates a new map by parsing the given subrange of str with the given PartialParser for keys and for values, with entries separated by entrySeparator, such as ", " and the keys separated from values by keyValueSeparator, such as "=".
      Various PartialParser instances are defined as constants, such as PartialParser.DEFAULT_STRING, and others can be created by static methods in PartialParser, such as PartialParser.objectListParser(PartialParser, String, boolean).
      Parameters:
      str - a String containing parseable text
      entrySeparator - the String separating every key-value pair
      keyValueSeparator - the String separating every key from its corresponding value
      keyParser - a PartialParser that returns a K key from a section of str
      valueParser - a PartialParser that returns a V value from a section of str
      offset - the first position to read parseable text from in str
      length - how many chars to read; -1 is treated as maximum length