com.ajjpj.afoundation.collection.immutable.AMap Maven / Gradle / Ivy
package com.ajjpj.afoundation.collection.immutable;
import com.ajjpj.afoundation.collection.AEquality;
import com.ajjpj.afoundation.function.AFunction1;
import java.io.Serializable;
import java.util.Iterator;
/**
* This interface represents immutable maps with mutator methods (updated(), removed()
) that return a
* new map instance with different members. Since all instances are immutable, they are thread-safe by definition.
* They are also useful in recursive algorithms.
*
* This interface does not implement java.util.Map
since that interface is inherently mutable. There is
* however a conversion method to java.util.Map
, and AMap implementations have factory methods that
* take java.util.Map
instances.
*
* The AMap contract is not hard-wired to equals()
and hashCode()
methods.
* Implementations are configurable through a pluggable equalityForEquals strategy, which defaults to equals() and hashCode()
* however. That allows e.g. using all AMap implementations based on object identity ('==') along the lines of what
* java.util.IdentityHashMap
does.
*
* Implementations (AHashMap in particular) use highly optimized algorithms to minimize 'copying' on modification.
*
* @author arno
*/
public interface AMap extends Iterable>, Serializable {
/**
* @return an {@link AEquality} that returns {@code true} if and only if two elements are
* 'equal' in the sense that one would replace the other as a key.
*/
AEquality keyEquality ();
/**
* @return an empty {@link AMap} instance of the same type and configuration as this instance.
*/
AMap clear();
/**
* @return the number of key-value pairs in this map.
*/
int size();
/**
* @return true if and only if this map's {@link #size()} is 0.
*/
boolean isEmpty();
/**
* @return true if and only if this map's {@link #size()} greater than 0.
*/
boolean nonEmpty();
/**
* Returns true iff the map contains the specified key. The containment check is based on the implementation's
* equalityForEquals strategy, which may or may not use equals()
.
*/
boolean containsKey(K key);
/**
* Returns true iff the map contains the specified value.
*/
boolean containsValue(V value);
/**
* Returns the value stored for a given key. If the map contains the key, the corresponding value is wrapped in
* AOption.some(...), otherwise AOption.none() is returned.
*/
AOption get(K key);
/**
* This is the equivalent of calling get(...).get(); implementations throw a NoSuchElementException if there is
* no entry for the key.
*/
V getRequired(K key);
/**
* This method 'adds' a new value for a given key, returning a modified copy of the map while leaving the original
* unmodified.
*/
AMap updated(K key, V value);
/**
* This method 'removes' an entry from the map, returning a modified copy of the map while leaving the original
* unmodified.
*/
AMap removed(K key);
/**
* Returns an iterator with all key/value pairs stored in the map. This method allows AMap instances to be used
* with the for(...: map)
syntax introduced with Java 5.
*/
@Override Iterator> iterator();
/**
* Returns an java.util.Set
with the map's keys. The returned object throws
* UnsupportedOperationException
for all modifying operations.
*
* The returned set is not guaranteed to provide uniqueness with regard to equals()
. If the
* map's equalityForEquals strategy treats two objects as different even if their equals
methods return true,
* then the returned set may contain both.
*/
ASet keys();
/**
* Returns a java.util.Collection
with the map's values. Duplicate values are returned as often as they
* occur. The returned collection throws UnsupportedOperationException
for all modifying operations.
*/
ACollection values();
/**
* Returns a read-only java.util.Map
view of the AMap. Constructing the view takes constant time (i.e.
* there is no copying), lookup and iteration are passed to the underlying AMap. All modifying operations on the
* returned Map throw UnsupportedOperationException
.
*/
java.util.Map asJavaUtilMap();
/**
* This method wraps an AMap, causing a given defaultValue to be returned for all keys not explicitly present in
* the map. Looking up the value for a key not explicitly stored in the map does not modify the map.
*/
AMap withDefaultValue(V defaultValue);
/**
* This method wraps an AMap. If one of the get...
methods is called for a key not stored in the map,
* a function is called to determine the value to be returned.
*
* NB: This does not cause the calculated value to be stored in the map; repeated calls for the same
* key trigger the value's calculation anew each time.
*/
AMap withDefault(AFunction1 super K, ? extends V, ? extends RuntimeException> function);
}