de.caff.generics

## Interface Dict<K,V>

- All Known Implementing Classes:
    Dict.Base

      public interface Dict<K,V>

  A dictionary. This is basically the same as `Map`, but optimized for read-only handling and non-zero values. This is defined as an immutable interface, but depending on its usage it might nevertheless change:
  - As this is often used as a view of a `Map` changes of the underlying map will be reflected. If this is a problem use `frozen()` to get a decoupled `Dict`.
  - It is generally a questionable idea to use mutable objects as map keys, here or in standard `Map`s. Any guarantees are void if a key changes. Think twice before doing this.
  - Changes to mutable values are also reflected, but this may be exactly what you want. Otherwise copy the values before you put them in the underlying map (only if they are still kept outside of the map) and use `viewMap(Map, Function)` to create the `Dict` with a function which copies the value. Thus each `get(Object)` will copy the value before returning it, so the internal value will never change. If you want to have both freezing and copying the correct calling order is `dict = Dict.viewMap(map).frozen().valueView(copyFunction)`
  Own on-the-fly implementations should extend `Dict.Base` as it provides some standard object methods. Other implementations might want to make use of `equal(Dict, Object)` in their `Object.equals(Object)` method (use `Types.hash(entries())` for your `Object.hashCode()` implementation then), and `toString(Dict)` in their `Object.toString()` method.

  All methods of this interface which return a `Dict` are silently returning a `Dict.Base` object.

  Since:
    September 29, 2021
  Author:
    Rammi

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Interface and Description
    --- | ---
    `static class` | `Dict.Base<KK,VV>` Abstract base class which provides useful implementations for `Object.equals(Object)`, `Object.hashCode()`, `Object.toString()`.
    `static class` | `Dict.Entry<EK,EV>` Entry access.

  - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static Dict<?,?>` | `EMPTY` Empty dictionary implementation.

  - ### Method Summary

    All Methods Static Methods Instance Methods Abstract Methods Default Methods
    Modifier and Type | Method and Description
    --- | ---
    `default void` | `addAllTo(java.util.Map<? super K,? super V> map)` Add all entries in this dictionary to the given map.
    `default Dict.Base<K,V>` | `asBase()` Convert this into a `Dict.Base` to have useful implementations for some standard Object methods.
    `default <T> T` | `digest(K key, java.util.function.BiFunction<? super K,? super V,? extends T> digester)` Call a function for the key-value pair if it exists, or return `null` if not.
    `default <T,E extends java.lang.Exception> T` | `digestFragile(K key, FragileFunction2<? extends T,E,? super K,? super V> digester)` Call a fragile function for the key-value pair if it exists, and return the result; or return null if it does not exist.
    `default <T,E extends java.lang.Exception> T` | `digestFragileOrElse(K key, FragileFunction2<? extends T,E,? super K,? super V> digester, java.util.function.Function<? super K,? extends T> elseDigester)` Call a fragile function for the key-value pair if it exists, or a function for the non-existing key.
    `default <T> T` | `digestOrElse(K key, java.util.function.BiFunction<? super K,? super V,? extends T> digester, java.util.function.Function<? super K,? extends T> elseDigester)` Call a function for the key-value pair if it exists, or a function for the non-existing key.
    `static <KT,VT> Dict<KT,VT>` | `empty()` Get an empty dictionary.
    `Countable<Dict.Entry<K,V>>` | `entries()` Get the entries of this dictionary.
    `static <KK,VV> boolean` | `equal(Dict<KK,VV> dict, java.lang.Object o)` Useful implementation for equality which can be used in `Dict` implementations for `Object.equals(Object)`.
    `default Dict<K,V>` | `filtered(java.util.function.Predicate<? super Dict.Entry<? super K,? super V>> check)` Get a filtered version of this dictionary.
    `default void` | `forEachEntry(java.util.function.BiConsumer<? super K,? super V> consumer)` Call a procedure for each entry.
    `default <E extends java.lang.Exception> void` | `forEachEntryFragile(FragileProcedure2<E,? super K,? super V> consumer)` Call a procedure which might throw an exception for each entry.
    `static <TK,TV> Dict<TK,TV>` | `fromTuples(java.lang.Iterable<? extends ITuple2<? extends TK,? extends TV>> entries)` Create a dictionary from a bunch of tuples.
    `default Dict<K,V>` | `frozen()` Get a frozen version of this dictionary.
    `V` | `get(K key)` Get the value for the given key.
    `default V` | `getNonNull(K key)` Get the value for the given key.
    `default V` | `getOr(K key, java.util.function.Function<? super K,? extends V> provider)` Get the value for the given key.
    `default V` | `getOrDefault(K key, V defaultValue)` Get the value for the given key.
    `default boolean` | `hasKey(K key)` Does this dictionary provide a value for the given key?
    `default boolean` | `isEmpty()` Is this map empty?
    `default Countable<K>` | `keys()` Get the keys of this dictionary.
    `default V` | `require(K key)` Get the value for the given key.
    `default V` | `requireNonNull(K key)` Get the value for the given key, and make sure it is not `null`.
    `static <KT,VT> Dict<KT,VT>` | `singleton(KT key, VT value)` Get a dictionary with a single entry.
    `default int` | `size()` Get the size of this dictionary.
    `default <E extends java.lang.Exception> void` | `supplyFragileOrElse(K key, FragileProcedure2<E,? super K,? super V> consumer, java.util.function.Consumer<? super K> elseConsumer)` Call a consumer if a given key exists, and another one, if not.
    `default void` | `supplyOrElse(K key, java.util.function.BiConsumer<? super K,? super V> consumer, java.util.function.Consumer<? super K> elseConsumer)` Call a consumer if a given key exists, and another one, if not.
    `static java.lang.String` | `toString(Dict<?,?> dict)` Creat a string representation from the given dictionary.
    `default boolean` | `trySupply(K key, java.util.function.BiConsumer<? super K,? super V> consumer)` Call a consumer for a key and its value if the key exists.
    `default <E extends java.lang.Exception> boolean` | `trySupplyFragile(K key, FragileProcedure2<E,? super K,? super V> consumer)` Call a fragile consumer for a key and its value if the key exists.
    `default Countable<V>` | `values()` Get the values of this dictionary.
    `default <NV> Dict<K,NV>` | `valueView(java.util.function.Function<? super V,? extends NV> valueMapper)` Get a view of this dictionary which seems as it has a different value type.
    `static <MK,MV> Dict<MK,MV>` | `viewMap(java.util.Map<? extends MK,? extends MV> map)` Create an read-only view of a standard map as if it is a dictionary.
    `static <MK,MV,DV> Dict<MK,DV>` | `viewMap(java.util.Map<MK,MV> map, java.util.function.Function<? super MV,? extends DV> valueMapper)` Create a read-only view of a standard map as if it is a dictionary and has a different value type.
    `static <MK1,MK2,MV> Dict<MK1,Dict<MK2,MV>>` | `viewMap2(java.util.Map<MK1,java.util.Map<MK2,MV>> map)` View a standard 2-dimensional map as 2-dimensional dictionary.
    `static <MK1,MK2,MV,DV> Dict<MK1,Dict<MK2,DV>>` | `viewMap2(java.util.Map<MK1,java.util.Map<MK2,MV>> map, java.util.function.Function<? super MV,? extends DV> valueMapper)` View a standard 2-dimensional map as 2-dimensional dictionary with a different inner value type.
    `static <MK,MV> Dict<MK,MV>` | `viewNullableMap(java.util.Map<? extends MK,? extends MV> map)` Create a read-only view of a map which is possibly `null`.
    `static <MK,MV,DV> Dict<MK,DV>` | `viewNullableMap(java.util.Map<MK,MV> map, java.util.function.Function<? super MV,? extends DV> valueMapper)` Create a read-only view of a standard map as if it is a dictionary and has a different value type.

- - ### Field Detail

    - #### EMPTY

          static final Dict<?,?> EMPTY

      Empty dictionary implementation. Use `empty()` instead.

  - ### Method Detail

    - #### fromTuples

          @NotNull
          static <TK,TV> Dict<TK,TV> fromTuples(@NotNull
                                                         java.lang.Iterable<? extends ITuple2<? extends TK,? extends TV>> entries)

      Create a dictionary from a bunch of tuples. It is assumed that `ITuple2._1()` defines the key, and `ITuple2._2()` the value.
      Type Parameters:
        `TK` - key type
        `TV` - value type
      Parameters:
        `entries` - dictionary entries defined as 2-tuples
      Returns:
        dictionary created from the given tuples

    - #### get

          @Nullable
          V get(K key)

      Get the value for the given key.
      Parameters:
        `key` - key
      Returns:
        value associated with key, or `null` if there is none
      See Also:
        `getNonNull(Object)`

    - #### entries

          @NotNull
          Countable<Dict.Entry<K,V>> entries()

      Get the entries of this dictionary.
      Returns:
        entries of this dictionary

    - #### getNonNull

          @NotNull
          default V getNonNull(K key)

      Get the value for the given key. This method will never return `null` but throw a `NullPointerException` instead. Depending on the underlying mapping `null` values might be acceptable, but will result in an exception nevertheless.
      Parameters:
        `key` - key
      Returns:
        non-null value associated with key
      Throws:
        `java.lang.NullPointerException` - if the return value would have been `null`
      See Also:
        `getOrDefault(Object, Object)`

    - #### getOrDefault

          @NotNull
          default V getOrDefault(K key,
                                          @NotNull
                                          V defaultValue)

      Get the value for the given key. Return a default if the key is not contained or if the associated value is `null`.
      Parameters:
        `key` - key
        `defaultValue` - default value used as fallback
      Returns:
        associated value or `defaultValue`

    - #### getOr

          default V getOr(K key,
                          @NotNull
                          java.util.function.Function<? super K,? extends V> provider)

      Get the value for the given key. If value is not defined, create it with a provider.
      Parameters:
        `key` - key
        `provider` - provider which is called when the key is not contain or the associated value is `null`, called with the key to provide the value which is returned
      Returns:
        associated value or a value created by `provider`

    - #### require

          @Nullable
          default V require(K key)

      Get the value for the given key. Throw a `NoSuchElementException` if the key is not contained.
      Parameters:
        `key` - key
      Returns:
        associated value, `null` if the associated value is `null`
      Throws:
        `java.util.NoSuchElementException` - if there is no such key

    - #### requireNonNull

          @NotNull
          default V requireNonNull(K key)

      Get the value for the given key, and make sure it is not `null`. Throw a `NoSuchElementException` if the key is not contained.
      Parameters:
        `key` - key
      Returns:
        associated value
      Throws:
        `java.util.NoSuchElementException` - if there is no such key
        `java.lang.NullPointerException` - if the key is valid, but the associated value is `null`

    - #### size

          default int size()

      Get the size of this dictionary.
      Returns:
        size

    - #### isEmpty

          default boolean isEmpty()

      Is this map empty?
      Returns:
        `true` if this map has no entries
        `false` otherwise

    - #### hasKey

          default boolean hasKey(K key)

      Does this dictionary provide a value for the given key?
      Parameters:
        `key` - key to check
      Returns:
        `true` if the given key is contained in this dictionary
        `false` if not

    - #### valueView

          @NotNull
          default <NV> Dict<K,NV> valueView(@NotNull
                                                     java.util.function.Function<? super V,? extends NV> valueMapper)

      Get a view of this dictionary which seems as it has a different value type.
      Type Parameters:
        `NV` - new value type
      Parameters:
        `valueMapper` - mapper which maps outgoing values toi the expected type. The mapper may assume non-`null` values.
      Returns:
        view of this dictionary with different value type

    - #### asBase

          @NotNull
          default Dict.Base<K,V> asBase()

      Convert this into a `Dict.Base` to have useful implementations for some standard Object methods.
      Returns:
        this converted into a Base or this itself if this is already a base

    - #### frozen

          @NotNull
          default Dict<K,V> frozen()

      Get a frozen version of this dictionary.

      Often `Dict` is used as a wrapper to an underlying `Map`. This means that changes to this map will be reflected by the wrapping Dict which usually is counter-intuitive because this interface is immutable. In cases where this might be a problem this method decouples the returned `Dict` so it is immutable under all sane circumstances.

      The implementation takes care to keep the order of `entries()`.

      Returns:
        frozen dictionary, or `this` if this is already frozen

    - #### values

          @NotNull
          default Countable<V> values()

      Get the values of this dictionary.
      Returns:
        dictionary values

    - #### keys

          @NotNull
          default Countable<K> keys()

      Get the keys of this dictionary.
      Returns:
        key of this dictionary

    - #### filtered

          @NotNull
          default Dict<K,V> filtered(@NotNull
                                              java.util.function.Predicate<? super Dict.Entry<? super K,? super V>> check)

      Get a filtered version of this dictionary.
      Parameters:
        `check` - check which decides which entries are kept
      Returns:
        filtered dictionary which only has approved entries

    - #### forEachEntry

          default void forEachEntry(@NotNull
                                    java.util.function.BiConsumer<? super K,? super V> consumer)

      Call a procedure for each entry.
      Parameters:
        `consumer` - procedure called for each entry with key and value
      See Also:
        `forEachEntryFragile(FragileProcedure2)`

    - #### forEachEntryFragile

          default <E extends java.lang.Exception> void forEachEntryFragile(@NotNull
                                                                           FragileProcedure2<E,? super K,? super V> consumer)
                                                                    throws E extends java.lang.Exception

      Call a procedure which might throw an exception for each entry.
      Type Parameters:
        `E` - exception which might be thrown by `consumer`
      Parameters:
        `consumer` - procedure called for each entry with key and value
      Throws:
        `E` - forwarded exception if `consumer` throws
        `E extends java.lang.Exception`

    - #### addAllTo

          default void addAllTo(@NotNull
                                java.util.Map<? super K,? super V> map)

      Add all entries in this dictionary to the given map.
      Parameters:
        `map` - map to collect the key-value pairs of this dictionary

    - #### trySupply

          default boolean trySupply(@NotNull
                                    K key,
                                    @NotNull
                                    java.util.function.BiConsumer<? super K,? super V> consumer)

      Call a consumer for a key and its value if the key exists.
      Parameters:
        `key` - key to check
        `consumer` - called with the key and the associated value if the key exists, not called if the key is not contained in this dict
      Returns:
        `true`: if the key exists and the consumer was called,
        `false` if the key is not present, and the consumer wasn't called

    - #### trySupplyFragile

          default <E extends java.lang.Exception> boolean trySupplyFragile(@NotNull
                                                                           K key,
                                                                           @NotNull
                                                                           FragileProcedure2<E,? super K,? super V> consumer)
                                                                    throws E extends java.lang.Exception

      Call a fragile consumer for a key and its value if the key exists.
      Type Parameters:
        `E` - exception type
      Parameters:
        `key` - key to check
        `consumer` - called with the key and the associated value if the key exists, not called if the key is not contained in this dict
      Returns:
        `true`: if the key exists and the consumer was called,
        `false` if the key is not present, and the consumer wasn't called
      Throws:
        `E` - if consumer throws
        `E extends java.lang.Exception`

    - #### supplyOrElse

          default void supplyOrElse(@NotNull
                                    K key,
                                    @NotNull
                                    java.util.function.BiConsumer<? super K,? super V> consumer,
                                    @NotNull
                                    java.util.function.Consumer<? super K> elseConsumer)

      Call a consumer if a given key exists, and another one, if not.
      Parameters:
        `key` - key to check
        `consumer` - consumer called with key and value if the key is present
        `elseConsumer` - consumer called with the key if the key is not present

    - #### supplyFragileOrElse

          default <E extends java.lang.Exception> void supplyFragileOrElse(@NotNull
                                                                           K key,
                                                                           @NotNull
                                                                           FragileProcedure2<E,? super K,? super V> consumer,
                                                                           @NotNull
                                                                           java.util.function.Consumer<? super K> elseConsumer)
                                                                    throws E extends java.lang.Exception

      Call a consumer if a given key exists, and another one, if not.
      Type Parameters:
        `E` - exception type
      Parameters:
        `key` - key to check
        `consumer` - consumer called with key and value if the key is present
        `elseConsumer` - consumer called with the key if the key is not present
      Throws:
        `E` - if `consumer` throws
        `E extends java.lang.Exception`

    - #### digestOrElse

          default <T> T digestOrElse(@NotNull
                                     K key,
                                     @NotNull
                                     java.util.function.BiFunction<? super K,? super V,? extends T> digester,
                                     @NotNull
                                     java.util.function.Function<? super K,? extends T> elseDigester)

      Call a function for the key-value pair if it exists, or a function for the non-existing key.
      Type Parameters:
        `T` - return type
      Parameters:
        `key` - key to checked
        `digester` - called if the key exists with key and value
        `elseDigester` - called if the key does not exist, with only the key
      Returns:
        result of either function

    - #### digest

          @Nullable
          default <T> T digest(@NotNull
                                         K key,
                                         @NotNull
                                         java.util.function.BiFunction<? super K,? super V,? extends T> digester)

      Call a function for the key-value pair if it exists, or return `null` if not.
      Type Parameters:
        `T` - return type
      Parameters:
        `key` - key to checked
        `digester` - called if the key exists with key and value
      Returns:
        result of the digester if the key-value pair is present, or `null` if not

    - #### digestFragileOrElse

          default <T,E extends java.lang.Exception> T digestFragileOrElse(@NotNull
                                                                          K key,
                                                                          @NotNull
                                                                          FragileFunction2<? extends T,E,? super K,? super V> digester,
                                                                          @NotNull
                                                                          java.util.function.Function<? super K,? extends T> elseDigester)
                                                                   throws E extends java.lang.Exception

      Call a fragile function for the key-value pair if it exists, or a function for the non-existing key.
      Type Parameters:
        `T` - return type
        `E` - exception type
      Parameters:
        `key` - key to checked
        `digester` - called if the key exists with key and value
        `elseDigester` - called if the key does not exist, with only the key
      Returns:
        result of either function
      Throws:
        `E` - if the digester throws
        `E extends java.lang.Exception`

    - #### digestFragile

          @Nullable
          default <T,E extends java.lang.Exception> T digestFragile(@NotNull
                                                                              K key,
                                                                              @NotNull
                                                                              FragileFunction2<? extends T,E,? super K,? super V> digester)
                                                                       throws E extends java.lang.Exception

      Call a fragile function for the key-value pair if it exists, and return the result; or return null if it does not exist.
      Type Parameters:
        `T` - return type
        `E` - exception type
      Parameters:
        `key` - key to checked
        `digester` - called if the key exists with key and value
      Returns:
        result of the digester if the key-value pair is present, or `null` if not
      Throws:
        `E` - if the digester throws
        `E extends java.lang.Exception`

    - #### empty

          @NotNull
          static <KT,VT> Dict<KT,VT> empty()

      Get an empty dictionary.
      Type Parameters:
        `KT` - key type
        `VT` - value type
      Returns:
        empty dictionary

    - #### singleton

          @NotNull
          static <KT,VT> Dict<KT,VT> singleton(@NotNull
                                                        KT key,
                                                        @NotNull
                                                        VT value)

      Get a dictionary with a single entry.
      Type Parameters:
        `KT` - key type
        `VT` - value type
      Parameters:
        `key` - single key
        `value` - associated value
      Returns:
        dictionary with single entry

    - #### viewMap

          @NotNull
          static <MK,MV> Dict<MK,MV> viewMap(@NotNull
                                                      java.util.Map<? extends MK,? extends MV> map)

      Create an read-only view of a standard map as if it is a dictionary.
      Type Parameters:
        `MK` - map and dictionary key type
        `MV` - map and dictionary value type
      Parameters:
        `map` - map which is expected not to change nor to have `null` values
      Returns:
        dictionary view of the standard map

    - #### viewNullableMap

          @NotNull
          static <MK,MV> Dict<MK,MV> viewNullableMap(@Nullable
                                                              java.util.Map<? extends MK,? extends MV> map)

      Create a read-only view of a map which is possibly `null`. If it is `null` return an empty dict, otherwise behave like `viewMap(Map)`.
      Type Parameters:
        `MK` - map and dictionary key type
        `MV` - map and dictionary value type
      Parameters:
        `map` - map which may itself be `null` but is expected not to change nor to have `null` values
      Returns:
        dictionary view of the standard map, empty if it is `null`

    - #### viewMap

          @NotNull
          static <MK,MV,DV> Dict<MK,DV> viewMap(@NotNull
                                                         java.util.Map<MK,MV> map,
                                                         @NotNull
                                                         java.util.function.Function<? super MV,? extends DV> valueMapper)

      Create a read-only view of a standard map as if it is a dictionary and has a different value type.
      Type Parameters:
        `MK` - map and dictionary key type
        `MV` - map value type
        `DV` - dictionary value type
      Parameters:
        `map` - map which is expected not to change nor to have `null` keys or values
        `valueMapper` - mapper which prepares values before they are returned
      Returns:
        dictionary view of the standard map with adapted value type

    - #### viewNullableMap

          @NotNull
          static <MK,MV,DV> Dict<MK,DV> viewNullableMap(@Nullable
                                                                 java.util.Map<MK,MV> map,
                                                                 @NotNull
                                                                 java.util.function.Function<? super MV,? extends DV> valueMapper)

      Create a read-only view of a standard map as if it is a dictionary and has a different value type. This takes care of `null` values, otherwise it calls `viewMap(Map, Function)`.
      Type Parameters:
        `MK` - map and dictionary key type
        `MV` - map value type
        `DV` - dictionary value type
      Parameters:
        `map` - map which itself may be `null` but is expected not to change nor to have `null` keys or values
        `valueMapper` - mapper which prepares values before they are returned
      Returns:
        dictionary view of the standard map with adapted value type, empty if `map` is `null`

    - #### viewMap2

          @NotNull
          static <MK1,MK2,MV> Dict<MK1,Dict<MK2,MV>> viewMap2(@NotNull
                                                                       java.util.Map<MK1,java.util.Map<MK2,MV>> map)

      View a standard 2-dimensional map as 2-dimensional dictionary.
      Type Parameters:
        `MK1` - outer key type
        `MK2` - inner key type
        `MV` - value type
      Parameters:
        `map` - standard 2d map
      Returns:
        2d dictionary

    - #### viewMap2

          @NotNull
          static <MK1,MK2,MV,DV> Dict<MK1,Dict<MK2,DV>> viewMap2(@NotNull
                                                                          java.util.Map<MK1,java.util.Map<MK2,MV>> map,
                                                                          @NotNull
                                                                          java.util.function.Function<? super MV,? extends DV> valueMapper)

      View a standard 2-dimensional map as 2-dimensional dictionary with a different inner value type.
      Type Parameters:
        `MK1` - outer key type
        `MK2` - inner key type
        `MV` - inner map value type (incoming)
        `DV` - inner dictionary value type (returned)
      Parameters:
        `map` - standard 2d map
        `valueMapper` - mapper which prepares values before they are returned
      Returns:
        2d dictionary with adapted inner value type

    - #### equal

          static <KK,VV> boolean equal(@NotNull
                                       Dict<KK,VV> dict,
                                       @NotNull
                                       java.lang.Object o)

      Useful implementation for equality which can be used in `Dict` implementations for `Object.equals(Object)`.

      It depends on the order of the entries returned by `entries`, so a `Object.hashCode()` should return `Types.hash(entries())`.

      Type Parameters:
        `KK` - key type
        `VV` - value type
      Parameters:
        `dict` - dict
        `o` - other object
      Returns:
        `true`

    - #### toString

          @NotNull
          static java.lang.String toString(@NotNull
                                                    Dict<?,?> dict)

      Creat a string representation from the given dictionary.
      Parameters:
        `dict` - dictionary
      Returns:
        string representation