1 /*
   2  * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * The Universal Permissive License (UPL), Version 1.0
   6  *
   7  * Subject to the condition set forth below, permission is hereby granted to any
   8  * person obtaining a copy of this software, associated documentation and/or
   9  * data (collectively the "Software"), free of charge and under any and all
  10  * copyright rights in the Software, and any and all patent rights owned or
  11  * freely licensable by each licensor hereunder covering either (i) the
  12  * unmodified Software as contributed to or provided by such licensor, or (ii)
  13  * the Larger Works (as defined below), to deal in both
  14  *
  15  * (a) the Software, and
  16  *
  17  * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
  18  * one is included with the Software each a "Larger Work" to which the Software
  19  * is contributed by such licensors),
  20  *
  21  * without restriction, including without limitation the rights to copy, create
  22  * derivative works of, display, perform, and distribute the Software and make,
  23  * use, sell, offer for sale, import, export, have made, and have sold the
  24  * Software and the Larger Work(s), and to sublicense the foregoing rights on
  25  * either these or other terms.
  26  *
  27  * This license is subject to the following condition:
  28  *
  29  * The above copyright notice and either this complete permission notice or at a
  30  * minimum a reference to the UPL must be included in all copies or substantial
  31  * portions of the Software.
  32  *
  33  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  34  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  35  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  36  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  37  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  38  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  39  * SOFTWARE.
  40  */
  41 package jdk.internal.vm.compiler.collections;
  42 
  43 import java.util.Iterator;
  44 import java.util.Map;
  45 import java.util.function.BiFunction;
  46 
  47 /**
  48  * Memory efficient map data structure.
  49  *
  50  * @since 1.0
  51  */
  52 public interface EconomicMap<K, V> extends UnmodifiableEconomicMap<K, V> {
  53 
  54     /**
  55      * Associates {@code value} with {@code key} in this map. If the map previously contained a
  56      * mapping for {@code key}, the old value is replaced by {@code value}.
  57      *
  58      * @return the previous value associated with {@code key}, or {@code null} if there was no
  59      *         mapping for {@code key}.
  60      * @since 1.0
  61      */
  62     V put(K key, V value);
  63 
  64     /**
  65      * Copies all of the mappings from {@code other} to this map.
  66      *
  67      * @since 1.0
  68      */
  69     default void putAll(EconomicMap<K, V> other) {
  70         MapCursor<K, V> e = other.getEntries();
  71         while (e.advance()) {
  72             put(e.getKey(), e.getValue());
  73         }
  74     }
  75 
  76     /**
  77      * Copies all of the mappings from {@code other} to this map.
  78      *
  79      * @since 1.0
  80      */
  81     default void putAll(UnmodifiableEconomicMap<? extends K, ? extends V> other) {
  82         UnmodifiableMapCursor<? extends K, ? extends V> entry = other.getEntries();
  83         while (entry.advance()) {
  84             put(entry.getKey(), entry.getValue());
  85         }
  86     }
  87 
  88     /**
  89      * Removes all of the mappings from this map. The map will be empty after this call returns.
  90      *
  91      * @since 1.0
  92      */
  93     void clear();
  94 
  95     /**
  96      * Removes the mapping for {@code key} from this map if it is present. The map will not contain
  97      * a mapping for {@code key} once the call returns.
  98      *
  99      * @return the previous value associated with {@code key}, or {@code null} if there was no
 100      *         mapping for {@code key}.
 101      * @since 1.0
 102      */
 103     V removeKey(K key);
 104 
 105     /**
 106      * Returns a {@link MapCursor} view of the mappings contained in this map.
 107      *
 108      * @since 1.0
 109      */
 110     @Override
 111     MapCursor<K, V> getEntries();
 112 
 113     /**
 114      * Replaces each entry's value with the result of invoking {@code function} on that entry until
 115      * all entries have been processed or the function throws an exception. Exceptions thrown by the
 116      * function are relayed to the caller.
 117      *
 118      * @since 1.0
 119      */
 120     void replaceAll(BiFunction<? super K, ? super V, ? extends V> function);
 121 
 122     /**
 123      * Creates a new map that guarantees insertion order on the key set with the default
 124      * {@link Equivalence#DEFAULT} comparison strategy for keys.
 125      *
 126      * @since 1.0
 127      */
 128     static <K, V> EconomicMap<K, V> create() {
 129         return EconomicMap.create(Equivalence.DEFAULT);
 130     }
 131 
 132     /**
 133      * Creates a new map that guarantees insertion order on the key set with the default
 134      * {@link Equivalence#DEFAULT} comparison strategy for keys and initializes with a specified
 135      * capacity.
 136      *
 137      * @since 1.0
 138      */
 139     static <K, V> EconomicMap<K, V> create(int initialCapacity) {
 140         return EconomicMap.create(Equivalence.DEFAULT, initialCapacity);
 141     }
 142 
 143     /**
 144      * Creates a new map that guarantees insertion order on the key set with the given comparison
 145      * strategy for keys.
 146      *
 147      * @since 1.0
 148      */
 149     static <K, V> EconomicMap<K, V> create(Equivalence strategy) {
 150         return EconomicMapImpl.create(strategy, false);
 151     }
 152 
 153     /**
 154      * Creates a new map that guarantees insertion order on the key set with the default
 155      * {@link Equivalence#DEFAULT} comparison strategy for keys and copies all elements from the
 156      * specified existing map.
 157      *
 158      * @since 1.0
 159      */
 160     static <K, V> EconomicMap<K, V> create(UnmodifiableEconomicMap<K, V> m) {
 161         return EconomicMap.create(Equivalence.DEFAULT, m);
 162     }
 163 
 164     /**
 165      * Creates a new map that guarantees insertion order on the key set and copies all elements from
 166      * the specified existing map.
 167      *
 168      * @since 1.0
 169      */
 170     static <K, V> EconomicMap<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> m) {
 171         return EconomicMapImpl.create(strategy, m, false);
 172     }
 173 
 174     /**
 175      * Creates a new map that guarantees insertion order on the key set and initializes with a
 176      * specified capacity.
 177      *
 178      * @since 1.0
 179      */
 180     static <K, V> EconomicMap<K, V> create(Equivalence strategy, int initialCapacity) {
 181         return EconomicMapImpl.create(strategy, initialCapacity, false);
 182     }
 183 
 184     /**
 185      * Wraps an existing {@link Map} as an {@link EconomicMap}.
 186      *
 187      * @since 1.0
 188      */
 189     static <K, V> EconomicMap<K, V> wrapMap(Map<K, V> map) {
 190         return new EconomicMap<K, V>() {
 191 
 192             @Override
 193             public V get(K key) {
 194                 V result = map.get(key);
 195                 return result;
 196             }
 197 
 198             @Override
 199             public V put(K key, V value) {
 200                 V result = map.put(key, value);
 201                 return result;
 202             }
 203 
 204             @Override
 205             public int size() {
 206                 int result = map.size();
 207                 return result;
 208             }
 209 
 210             @Override
 211             public boolean containsKey(K key) {
 212                 return map.containsKey(key);
 213             }
 214 
 215             @Override
 216             public void clear() {
 217                 map.clear();
 218             }
 219 
 220             @Override
 221             public V removeKey(K key) {
 222                 V result = map.remove(key);
 223                 return result;
 224             }
 225 
 226             @Override
 227             public Iterable<V> getValues() {
 228                 return map.values();
 229             }
 230 
 231             @Override
 232             public Iterable<K> getKeys() {
 233                 return map.keySet();
 234             }
 235 
 236             @Override
 237             public boolean isEmpty() {
 238                 return map.isEmpty();
 239             }
 240 
 241             @Override
 242             public MapCursor<K, V> getEntries() {
 243                 Iterator<java.util.Map.Entry<K, V>> iterator = map.entrySet().iterator();
 244                 return new MapCursor<K, V>() {
 245 
 246                     private Map.Entry<K, V> current;
 247 
 248                     @Override
 249                     public boolean advance() {
 250                         boolean result = iterator.hasNext();
 251                         if (result) {
 252                             current = iterator.next();
 253                         }
 254 
 255                         return result;
 256                     }
 257 
 258                     @Override
 259                     public K getKey() {
 260                         return current.getKey();
 261                     }
 262 
 263                     @Override
 264                     public V getValue() {
 265                         return current.getValue();
 266                     }
 267 
 268                     @Override
 269                     public void remove() {
 270                         iterator.remove();
 271                     }
 272                 };
 273             }
 274 
 275             @Override
 276             public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
 277                 map.replaceAll(function);
 278             }
 279         };
 280     }
 281 }