1 package org.opentrafficsim.base.immutablecollections; 2 3 import java.io.Serializable; 4 import java.util.ConcurrentModificationException; 5 import java.util.Map; 6 import java.util.Objects; 7 import java.util.Set; 8 import java.util.function.BiConsumer; 9 10 /** 11 * A Map interface without the methods that can change it. The constructor of the ImmutableMap needs to be given an initial Map. 12 * <p> 13 * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br> 14 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>. 15 * </p> 16 * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $, 17 * initial version May 7, 2016 <br> 18 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a> 19 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a> 20 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a> 21 * @param <K> the key type of content of this Map 22 * @param <V> the value type of content of this Map 23 */ 24 public interface ImmutableMap<K, V> extends Serializable 25 { 26 /** 27 * Returns the number of elements in this immutable collection. If this immutable collection contains more than 28 * <tt>Integer.MAX_VALUE</tt> elements, returns <tt>Integer.MAX_VALUE</tt>. 29 * @return the number of elements in this immutable collection 30 */ 31 int size(); 32 33 /** 34 * Returns <tt>true</tt> if this immutable collection contains no elements. 35 * @return <tt>true</tt> if this immutable collection contains no elements 36 */ 37 boolean isEmpty(); 38 39 /** 40 * Returns <tt>true</tt> if this map contains a mapping for the specified key. More formally, returns <tt>true</tt> if and 41 * only if this map contains a mapping for a key <tt>k</tt> such that <tt>(key==null ? k==null : key.equals(k))</tt>. (There 42 * can be at most one such mapping.) 43 * @param key key whose presence in this map is to be tested 44 * @return <tt>true</tt> if this map contains a mapping for the specified key 45 * @throws ClassCastException if the key is of an inappropriate type for this map 46 * @throws NullPointerException if the specified key is null and this map does not permit null keys 47 */ 48 boolean containsKey(Object key); 49 50 /** 51 * Returns <tt>true</tt> if this map maps one or more keys to the specified value. More formally, returns <tt>true</tt> if 52 * and only if this map contains at least one mapping to a value <tt>v</tt> such that 53 * <tt>(value==null ? v==null : value.equals(v))</tt>. This operation will probably require time linear in the map size for 54 * most implementations of the <tt>Map</tt> interface. 55 * @param value value whose presence in this map is to be tested 56 * @return <tt>true</tt> if this map maps one or more keys to the specified value 57 * @throws ClassCastException if the value is of an inappropriate type for this map 58 * @throws NullPointerException if the specified value is null and this map does not permit null values 59 */ 60 boolean containsValue(Object value); 61 62 /** 63 * Returns the value to which the specified key is mapped, or {@code null} if this map contains no mapping for the key. 64 * <p> 65 * More formally, if this map contains a mapping from a key {@code k} to a value {@code v} such that 66 * {@code (key==null ? k==null : key.equals(k))}, then this method returns {@code v}; otherwise it returns {@code null}. 67 * (There can be at most one such mapping.) 68 * <p> 69 * If this map permits null values, then a return value of {@code null} does not <i>necessarily</i> indicate that the map 70 * contains no mapping for the key; it's also possible that the map explicitly maps the key to {@code null}. The 71 * {@link #containsKey containsKey} operation may be used to distinguish these two cases. 72 * @param key the key whose associated value is to be returned 73 * @return the value to which the specified key is mapped, or {@code null} if this map contains no mapping for the key 74 * @throws ClassCastException if the key is of an inappropriate type for this map 75 * @throws NullPointerException if the specified key is null and this map does not permit null keys 76 */ 77 V get(Object key); 78 79 /** 80 * Returns a {@link Set} view of the keys contained in this map. 81 * @return an immutable set of the keys contained in this map 82 */ 83 ImmutableSet<K> keySet(); 84 85 /** 86 * Returns a {@link ImmutableCollection} view of the values contained in this map. 87 * @return an immutable collection view of the values contained in this map 88 */ 89 ImmutableCollection<V> values(); 90 91 /** 92 * Returns the value to which the specified key is mapped, or {@code defaultValue} if this map contains no mapping for the 93 * key. The default implementation makes no guarantees about synchronization or atomicity properties of this method. Any 94 * implementation providing atomicity guarantees must override this method and document its concurrency properties. 95 * @param key the key whose associated value is to be returned 96 * @param defaultValue the default mapping of the key 97 * @return the value to which the specified key is mapped, or {@code defaultValue} if this map contains no mapping for the 98 * key 99 * @throws ClassCastException if the key is of an inappropriate type for this map 100 * @throws NullPointerException if the specified key is null and this map does not permit null keys 101 */ 102 default V getOrDefault(Object key, V defaultValue) 103 { 104 V v = get(key); 105 return ((v != null) || containsKey(key)) ? v : defaultValue; 106 } 107 108 /** 109 * Performs the given action for each entry in this map until all entries have been processed or the action throws an 110 * exception. Unless otherwise specified by the implementing class, actions are performed in the order of entry set 111 * iteration (if an iteration order is specified.) Exceptions thrown by the action are relayed to the caller. The default 112 * implementation makes no guarantees about synchronization or atomicity properties of this method. Any implementation 113 * providing atomicity guarantees must override this method and document its concurrency properties. 114 * @param action The action to be performed for each entry 115 * @throws NullPointerException if the specified action is null 116 * @throws ConcurrentModificationException if an entry is found to be removed during iteration 117 */ 118 default void forEach(BiConsumer<? super K, ? super V> action) 119 { 120 Objects.requireNonNull(action); 121 for (Map.Entry<K, V> entry : toMap().entrySet()) 122 { 123 K k; 124 V v; 125 try 126 { 127 k = entry.getKey(); 128 v = entry.getValue(); 129 } 130 catch (IllegalStateException ise) 131 { 132 // this usually means the entry is no longer in the map. 133 throw new ConcurrentModificationException(ise); 134 } 135 action.accept(k, v); 136 } 137 } 138 139 /** 140 * Returns a modifiable copy of this immutable list. 141 * @return a modifiable copy of this immutable list. 142 */ 143 Map<K, V> toMap(); 144 145 /** 146 * Force to redefine equals for the implementations of immutable collection classes. 147 * @param obj the object to compare this collection with 148 * @return whether the objects are equal 149 */ 150 boolean equals(final Object obj); 151 152 /** 153 * Force to redefine hashCode for the implementations of immutable collection classes. 154 * @return the calculated hashCode 155 */ 156 int hashCode(); 157 158 /** 159 * Return whether the internal storage is a wrapped pointer to the original map. If true, this means that anyone holding a 160 * pointer to this data structure can still change it. The users of the ImmutableMap itself can, however, not make any 161 * changes. 162 * @return boolean; whether the internal storage is a wrapped pointer to the original map 163 */ 164 boolean isWrap(); 165 166 /** 167 * Return whether the internal storage is a (shallow) copy of the original map. If true, this means that anyone holding a 168 * pointer to the original of the data structure can not change it anymore. Nor can the users of the ImmutableMap itself 169 * make any changes. 170 * @return boolean; whether the internal storage is a safe copy of the original map 171 */ 172 default boolean isCopy() 173 { 174 return !isWrap(); 175 } 176 177 }