/* * Copyright 2013 Cameron Beccario * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.nullschool.collect; import java.util.*; /** * 2013-02-15<p/> * * A persistent (i.e., immutable) {@link IterableMap}. See a description of persistent data structures on * <a href="http://en.wikipedia.org/wiki/Persistent_data_structures">Wikipedia</a>.<p/> A ConstMap instance * is guaranteed to never visibly change. New associations can be created or removed using the {@link #with}, * {@link #without}, and related methods, which allocate a new instance if necessary while leaving the original * instance unchanged.<p/> * * Because a ConstMap is effectively immutable, the {@link #put}, {@link #putAll}, {@link #remove}, and * {@link #clear} methods inherited from {@link Map} always throw {@link UnsupportedOperationException}. They * are marked <i>deprecated</i> to signify to the developer that they should not be invoked. Furthermore, the * {@link #keySet}, {@link #values}, and {@link #entrySet} views are also persistent and cannot be used to mutate * the underlying map, either via their iterators' {@link Iterator#remove} method or the {@link Map.Entry#setValue} * method. * * @param <K> the key type * @param <V> the value type * * @author Cameron Beccario */ public interface ConstMap<K, V> extends IterableMap<K, V> { /** * Returns a ConstMap containing the associations of this map plus the specified key-value association. * No visible change to this map occurs. In this way, the {@code with} method may be considered a factory * method for creating new instances of ConstMap.<p/> * * If this map already contains the desired association, i.e., if the resulting map R would otherwise * equal this map, {@code R.equals(this)}, then the method may simply return this map, unchanged. * * @param key the key to associate * @param value the value to be associated with the key * @return a ConstMap containing this map's associations conjoined with the specified association. * @throws ClassCastException if the key or value is of a type not suitable for this or the resulting map. * @throws NullPointerException if the key or value is null and this or the resulting map does not allow nulls. * @throws IllegalArgumentException if some property of the key or value is not suitable for this or the * resulting map. */ ConstMap<K, V> with(K key, V value); /** * Returns a ConstMap containing the associations of this map plus all the associations of the specified * map. No visible change in this map occurs. In this way, the {@code withAll} method may be considered a * factory method for creating new instances of ConstMap.<p/> * * The effect of this call is equivalent to invoking {@link #with} for each entry in the specified map. If * this map already contains the desired associations, i.e., if the resulting map R would otherwise * equal this map, {@code R.equals(this)}, then the method may simply return this map, unchanged. * * @param map mappings to conjoin with the associations in this map * @return a ConstMap containing this map's associations conjoined with the associations in the provided map. * @throws ClassCastException if a key or value in the specified map is of a type not suitable for this or * the resulting map. * @throws NullPointerException if the specified map is null, or if a key or value in the specified map is * null and either this or the resulting map does not allow nulls. * @throws IllegalArgumentException if some property of a key or value in the specified map is not suitable * for this or the resulting map. */ ConstMap<K, V> withAll(Map<? extends K, ? extends V> map); /** * Returns a ConstMap containing the associations of this map minus the mapping for the specified key. * No visible change to this map occurs. In this way, the {@code without} method may be considered a factory * method for creating new instances of ConstMap.<p/> * * If this map does not contain the specified key, i.e., if the resulting map R would otherwise * equal this map, {@code R.equals(this)}, then the method may simply return this map, unchanged. * * @param key the key to de-associate. * @return a ConstMap containing this map's associations disjoined from the specified association. * @throws ClassCastException if the key is of a type not suitable for this map. * @throws NullPointerException if the key is null and this map does not allow nulls. */ ConstMap<K, V> without(Object key); /** * Returns a ConstMap containing the associations of this map minus all the mappings for the specified * keys. No visible change to this map occurs. In this way, the {@code withoutAll} method may be considered a * factory method for creating new instances of ConstMap.<p/> * * The effect of this call is equivalent to invoking {@link #without} for each key in the specified * collection. If this map does not contain any of the keys, i.e., if the resulting map R would otherwise * equal this map, {@code R.equals(this)}, then the method may simply return this map, unchanged. * * @param keys the keys to de-associate from this map. * @return a ConstMap containing this map's associations disjoined from the keys in the provided collection. * @throws ClassCastException if a key in the specified collection is of a type not suitable for this or * the resulting map. * @throws NullPointerException if the specified collection is null, or if a key in the specified collection * is null and either this or the resulting map does not allow nulls. */ ConstMap<K, V> withoutAll(Collection<?> keys); /** * Returns a {@link ConstSet} containing this map's keys. Because it is persistent, the key set should not be * considered a "view" of this map. For example, invocations of this set's {@link ConstSet#with} method have * no effect on this map and result in a {@link ConstSet} instance that is effectively independent. * * @return this map's keys as a persistent set. */ @Override ConstSet<K> keySet(); /** * Returns a {@link ConstCollection} containing this map's values. Because it is persistent, the value * collection should not be considered a "view" of this map. For example, invocations of this collection's * {@link ConstCollection#with} method have no effect on this map and result in a {@link ConstCollection} * instance that is effectively independent. * * @return this map's values as a persistent collection. */ @Override ConstCollection<V> values(); /** * Returns a {@link ConstSet} containing this map's entries. Because it is persistent, the entry set should * not be considered a "view" of this map. For example, invocations of this set's {@link ConstSet#with} method * have no effect on this map and result in a {@link ConstSet} instance that is effectively independent. * * @return this map's entries as a persistent set. */ @Override ConstSet<Entry<K, V>> entrySet(); // ================================================================================================================= // Mutation methods marked @Deprecated to signify they should not be invoked. /** * This method always throws {@link UnsupportedOperationException}. * @deprecated see {@link #with} */ @Deprecated @Override V put(K key, V value); /** * This method always throws {@link UnsupportedOperationException}. * @deprecated see {@link #withAll} */ @Deprecated @Override void putAll(Map<? extends K, ? extends V> map); /** * This method always throws {@link UnsupportedOperationException}. * @deprecated see {@link #without} */ @Deprecated @Override V remove(Object key); /** * This method always throws {@link UnsupportedOperationException}. * @deprecated see {@link #withoutAll} */ @Deprecated @Override void clear(); }