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  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  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 }