001/* 002 * Copyright (C) 2002-2015 Sebastiano Vigna 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package squidpony.squidmath; 017 018import squidpony.annotation.GwtIncompatible; 019 020import java.io.Serializable; 021import java.util.*; 022 023/** 024 * A generic insertion-ordered hash map with with a fast implementation, originally from fastutil as 025 * Object2ObjectLinkedOpenHashMap but modified to support constant-time indexed access of keys, values, and entries, 026 * reordering, and optional hash strategies for unusual keys, such as arrays or usually-dense numeric values. 027 * <br> 028 * Instances of this class use a hash table to represent a map. The table is filled up to a specified <em>load factor</em>, and then doubled in size to accommodate new entries. If the table is 029 * emptied below <em>one fourth</em> of the load factor, it is halved in size. However, halving is not performed when deleting entries from an iterator, as it would interfere with the iteration 030 * process. 031 * <br> 032 * Note that {@link #clear()} does not modify the hash table size. Rather, a family of {@linkplain #trim() trimming methods} lets you control the size of the table; this is particularly useful if 033 * you reuse instances of this class. 034 * <br> 035 * Iterators generated by this map will enumerate pairs in the same order in which they have been added to the map (addition of pairs whose key is already present in the set does not change the 036 * iteration order). Note that this order has nothing in common with the natural order of the keys. The order is kept by means of a int-specialized list, {@link IntVLA}, and is modifiable with this 037 * class' {@link #reorder(int...)} and {@link #shuffle(IRNG)} methods, among other tools. It may be preferable to avoid instantiating an Iterator object and instead 038 * use a normal int-based for loop with {@link #getAt(int)} called in each iteration. Though this doesn't allow easy deletion of items during iteration, it may be the 039 * fastest way to iterate through an OrderedMap. 040 * <br> 041 * This class implements the interface of a sorted map, so to allow easy access of the iteration order: for instance, you can get the first key in iteration order with {@code firstKey()} without 042 * having to create an iterator; however, this class partially violates the {@link SortedMap} contract because all submap methods throw an exception and {@link #comparator()} returns always 043 * <code>null</code>. 044 * <br> 045 * Additional methods, such as <code>getAndMoveToFirst()</code>, make it easy to use instances of this class as a cache (e.g., with LRU policy). 046 * <br> 047 * This class allows approximately constant-time lookup of keys or values by their index in the ordering, which can 048 * allow some novel usage of the data structure. {@link OrderedSet} can be used like a list of unique elements, keeping 049 * order like a list does but also allowing rapid checks for whether an item exists in the OrderedSet, and OrderedMap 050 * can be used like that but with values associated as well (where OrderedSet uses contains(), OrderedMap uses 051 * containsKey()). You can also set the key and value at a position with {@link #putAt(Object, Object, int)}, or alter 052 * the key while keeping its value and index the same with {@link #alter(Object, Object)}. Reordering works here too, 053 * both with completely random orders from {@link #shuffle(IRNG)} or with a previously-generated ordering from 054 * {@link #reorder(int...)} (you can produce such an ordering for a given size and reuse it across multiple Ordered data 055 * structures with {@link IRNG#randomOrdering(int)}). Note that putAt() and {@link #removeAt(int)} do not run in constant 056 * time, and depending on the point of insertion/removal, they are likely to run in linear time (but also note that most 057 * insertion-ordered Maps and Sets don't allow insertion or removal at anywhere but the beginning or end of the order). 058 * <br> 059 * You can pass a {@link CrossHash.IHasher} instance such as {@link CrossHash#generalHasher} as an extra parameter to 060 * most of this class' constructors, which allows the OrderedMap to use arrays (usually primitive arrays) as keys. If 061 * you expect only one type of array, you can use an instance like {@link CrossHash#intHasher} to hash int arrays, or 062 * the aforementioned generalHasher to hash most kinds of arrays (it can't handle most multi-dimensional arrays well). 063 * If you aren't using arrays as keys, you don't need to give an IHasher to the constructor and can ignore this feature 064 * most of the time. However, the default IHasher this uses if none is specified performs a small but significant 065 * "mixing" step to make the default generated hashCode() implementation many classes use into a higher-quality 066 * random-like value. This isn't always optimal; if you plan to insert 1000 sequential Integer keys with some small 067 * amount of random Integers after them, then the mixing actually increases the likelihood of a collision and takes time 068 * to calculate. You could use a very simple IHasher in that case, relying on the fact that only Integers will be added: 069 * <pre> 070 * new CrossHash.IHasher() { 071 * public int hash(Object data) { return (int)data; } 072 * public boolean areEqual(Object left, Object right) { return Objects.equals(left, right); } 073 * }; 074 * </pre> 075 * This is just one example of a case where a custom IHasher can be useful for performance reasons; there are also cases 076 * where an IHasher is needed to enforce hashing by identity or by value, which affect program logic. Note that the 077 * given IHasher is likely to be sub-optimal for many situations with Integer keys, and you may want to try a few 078 * different approaches if you know OrderedMap is a bottleneck in your application. If the IHasher is a performance 079 * problem, it will be at its worst if the OrderedMap needs to resize, and thus rehash, many times; this won't happen if 080 * the capacity is set correctly when the OrderedMap is created (with the capacity equal to or greater than the maximum 081 * number of entries that will be added). 082 * <br> 083 * Thank you, Sebastiano Vigna, for making FastUtil available to the public with such high quality. 084 * <br> 085 * See https://github.com/vigna/fastutil for the original library. 086 * @author Sebastiano Vigna (responsible for all the hard parts) 087 * @author Tommy Ettinger (mostly responsible for squashing several layers of parent classes into one monster class) 088 */ 089public class OrderedMap<K, V> implements SortedMap<K, V>, java.io.Serializable, Cloneable { 090 private static final long serialVersionUID = 0L; 091 /** 092 * The array of keys. 093 */ 094 protected K[] key; 095 /** 096 * The array of values. 097 */ 098 protected V[] value; 099 /** 100 * The mask for wrapping a position counter. 101 */ 102 protected int mask; 103 /** 104 * Whether this set contains the key zero. 105 */ 106 protected boolean containsNullKey; 107 /** 108 * An IntVLA (variable-length int sequence) that stores the positions in the key array of specific keys, with the 109 * positions in insertion order. The order can be changed with {@link #reorder(int...)} and other methods. 110 */ 111 protected IntVLA order; 112 /** 113 * The current table size. 114 */ 115 protected int n; 116 /** 117 * Threshold after which we rehash. It must be the table size times {@link #f}. 118 */ 119 protected int maxFill; 120 /** 121 * Number of entries in the set (including the key zero, if present). 122 */ 123 protected int size; 124 /** 125 * The acceptable load factor. 126 */ 127 public final float f; 128 /** 129 * Cached set of entries. 130 */ 131 protected volatile MapEntrySet entries; 132 /** 133 * Cached set of keys. 134 */ 135 protected volatile KeySet keys; 136 /** 137 * Cached collection of values. 138 */ 139 protected volatile Collection<V> values; 140 /** 141 * Default return value. 142 */ 143 protected V defRetValue; 144 145 /** 146 * The initial default size of a hash table. 147 */ 148 public static final int DEFAULT_INITIAL_SIZE = 16; 149 /** 150 * The default load factor of a hash table. 151 */ 152 public static final float DEFAULT_LOAD_FACTOR = .25f; // .1875f; // .75f; 153 /** 154 * The load factor for a (usually small) table that is meant to be particularly fast. 155 */ 156 public static final float FAST_LOAD_FACTOR = .5f; 157 /** 158 * The load factor for a (usually very small) table that is meant to be extremely fast. 159 */ 160 public static final float VERY_FAST_LOAD_FACTOR = .25f; 161 162 protected final CrossHash.IHasher hasher; 163 164 public void defaultReturnValue(final V rv) { 165 defRetValue = rv; 166 } 167 168 public V defaultReturnValue() { 169 return defRetValue; 170 } 171 172 /** 173 * Creates a new OrderedMap. 174 * <p> 175 * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>. 176 * 177 * @param expected the expected number of elements in the hash set. 178 * @param f the load factor. 179 */ 180 181 @SuppressWarnings("unchecked") 182 public OrderedMap(final int expected, final float f) { 183 if (f <= 0 || f > 1) 184 throw new IllegalArgumentException("Load factor must be greater than 0 and smaller than or equal to 1"); 185 if (expected < 0) throw new IllegalArgumentException("The expected number of elements must be nonnegative"); 186 this.f = f; 187 n = arraySize(expected, f); 188 mask = n - 1; 189 maxFill = maxFill(n, f); 190 key = (K[]) new Object[n + 1]; 191 value = (V[]) new Object[n + 1]; 192 //link = new long[n + 1]; 193 order = new IntVLA(expected); 194 hasher = CrossHash.mildHasher; 195 } 196 197 /** 198 * Creates a new OrderedMap with 0.75f as load factor. 199 * 200 * @param expected the expected number of elements in the OrderedMap. 201 */ 202 public OrderedMap(final int expected) { 203 this(expected, DEFAULT_LOAD_FACTOR); 204 } 205 206 /** 207 * Creates a new OrderedMap with initial expected 16 entries and 0.75f as load factor. 208 */ 209 public OrderedMap() { 210 this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR); 211 } 212 213 /** 214 * Creates a new OrderedMap copying a given one. 215 * 216 * @param m a {@link Map} to be copied into the new OrderedMap. 217 * @param f the load factor. 218 */ 219 public OrderedMap(final Map<? extends K, ? extends V> m, final float f) { 220 this(m.size(), f, (m instanceof OrderedMap) ? ((OrderedMap) m).hasher : CrossHash.mildHasher); 221 putAll(m); 222 } 223 224 /** 225 * Creates a new OrderedMap with 0.75f as load factor copying a given one. 226 * 227 * @param m a {@link Map} to be copied into the new OrderedMap. 228 */ 229 public OrderedMap(final Map<? extends K, ? extends V> m) { 230 this(m, (m instanceof OrderedMap) ? ((OrderedMap) m).f : DEFAULT_LOAD_FACTOR, (m instanceof OrderedMap) ? ((OrderedMap) m).hasher : CrossHash.mildHasher); 231 } 232 233 /** 234 * Creates a new OrderedMap using the elements of two parallel arrays. 235 * 236 * @param keyArray the array of keys of the new OrderedMap. 237 * @param valueArray the array of corresponding values in the new OrderedMap. 238 * @param f the load factor. 239 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths. 240 */ 241 public OrderedMap(final K[] keyArray, final V[] valueArray, final float f) { 242 this(keyArray.length, f); 243 if (keyArray.length != valueArray.length) 244 throw new IllegalArgumentException("The key array and the value array have different lengths (" + keyArray.length + " and " + valueArray.length + ")"); 245 for (int i = 0; i < keyArray.length; i++) 246 put(keyArray[i], valueArray[i]); 247 } 248 /** 249 * Creates a new OrderedMap using the elements of two parallel arrays. 250 * 251 * @param keyColl the collection of keys of the new OrderedMap. 252 * @param valueColl the collection of corresponding values in the new OrderedMap. 253 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths. 254 */ 255 public OrderedMap(final Collection<K> keyColl, final Collection<V> valueColl) { 256 this(keyColl, valueColl, DEFAULT_LOAD_FACTOR); 257 } 258 /** 259 * Creates a new OrderedMap using the elements of two parallel arrays. 260 * 261 * @param keyColl the collection of keys of the new OrderedMap. 262 * @param valueColl the collection of corresponding values in the new OrderedMap. 263 * @param f the load factor. 264 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths. 265 */ 266 public OrderedMap(final Collection<K> keyColl, final Collection<V> valueColl, final float f) { 267 this(keyColl.size(), f); 268 if (keyColl.size() != valueColl.size()) 269 throw new IllegalArgumentException("The key array and the value array have different lengths (" + keyColl.size() + " and " + valueColl.size() + ")"); 270 Iterator<K> ki = keyColl.iterator(); 271 Iterator<V> vi = valueColl.iterator(); 272 while (ki.hasNext() && vi.hasNext()) 273 { 274 put(ki.next(), vi.next()); 275 } 276 } 277 278 /** 279 * Creates a new OrderedMap with 0.75f as load factor using the elements of two parallel arrays. 280 * 281 * @param keyArray the array of keys of the new OrderedMap. 282 * @param valueArray the array of corresponding values in the new OrderedMap. 283 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths. 284 */ 285 public OrderedMap(final K[] keyArray, final V[] valueArray) { 286 this(keyArray, valueArray, DEFAULT_LOAD_FACTOR); 287 } 288 289 /** 290 * Creates a new OrderedMap. 291 * <p> 292 * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>. 293 * 294 * @param expected the expected number of elements in the hash set. 295 * @param f the load factor. 296 * @param hasher used to hash items; typically only needed when K is an array, where CrossHash has implementations 297 */ 298 299 @SuppressWarnings("unchecked") 300 public OrderedMap(final int expected, final float f, CrossHash.IHasher hasher) { 301 if (f <= 0 || f > 1) 302 throw new IllegalArgumentException("Load factor must be greater than 0 and smaller than or equal to 1"); 303 if (expected < 0) throw new IllegalArgumentException("The expected number of elements must be nonnegative"); 304 this.f = f; 305 n = arraySize(expected, f); 306 mask = n - 1; 307 maxFill = maxFill(n, f); 308 key = (K[]) new Object[n + 1]; 309 value = (V[]) new Object[n + 1]; 310 //link = new long[n + 1]; 311 order = new IntVLA(expected); 312 this.hasher = (hasher == null) ? CrossHash.mildHasher : hasher; 313 } 314 /** 315 * Creates a new OrderedMap with 0.75f as load factor. 316 * 317 * @param expected the expected number of elements in the OrderedMap. 318 * @param hasher used to hash items; typically only needed when K is an array, where CrossHash has implementations 319 */ 320 public OrderedMap(final int expected, CrossHash.IHasher hasher) { 321 this(expected, DEFAULT_LOAD_FACTOR, hasher); 322 } 323 324 /** 325 * Creates a new OrderedMap with initial expected 16 entries and 0.75f as load factor. 326 */ 327 public OrderedMap(CrossHash.IHasher hasher) { 328 this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, hasher); 329 } 330 331 /** 332 * Creates a new OrderedMap copying a given one. 333 * 334 * @param m a {@link Map} to be copied into the new OrderedMap. 335 * @param f the load factor. 336 * @param hasher used to hash items; typically only needed when K is an array, where CrossHash has implementations 337 */ 338 public OrderedMap(final Map<? extends K, ? extends V> m, final float f, CrossHash.IHasher hasher) { 339 this(m.size(), f, hasher); 340 putAll(m); 341 } 342 343 /** 344 * Creates a new OrderedMap with 0.75f as load factor copying a given one. 345 * @param m a {@link Map} to be copied into the new OrderedMap. 346 * @param hasher used to hash items; typically only needed when K is an array, where CrossHash has implementations 347 */ 348 public OrderedMap(final Map<? extends K, ? extends V> m, CrossHash.IHasher hasher) { 349 this(m, DEFAULT_LOAD_FACTOR, hasher); 350 } 351 352 /** 353 * Creates a new OrderedMap using the elements of two parallel arrays. 354 * 355 * @param keyArray the array of keys of the new OrderedMap. 356 * @param valueArray the array of corresponding values in the new OrderedMap. 357 * @param f the load factor. 358 * @param hasher used to hash items; typically only needed when K is an array, where CrossHash has implementations 359 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths. 360 */ 361 public OrderedMap(final K[] keyArray, final V[] valueArray, final float f, CrossHash.IHasher hasher) { 362 this(keyArray.length, f, hasher); 363 if (keyArray.length != valueArray.length) 364 throw new IllegalArgumentException("The key array and the value array have different lengths (" + keyArray.length + " and " + valueArray.length + ")"); 365 for (int i = 0; i < keyArray.length; i++) 366 put(keyArray[i], valueArray[i]); 367 } 368 /** 369 * Creates a new OrderedMap with 0.75f as load factor using the elements of two parallel arrays. 370 * 371 * @param keyArray the array of keys of the new OrderedMap. 372 * @param valueArray the array of corresponding values in the new OrderedMap. 373 * @param hasher used to hash items; typically only needed when K is an array, where CrossHash has implementations 374 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths. 375 */ 376 public OrderedMap(final K[] keyArray, final V[] valueArray, CrossHash.IHasher hasher) { 377 this(keyArray, valueArray, DEFAULT_LOAD_FACTOR, hasher); 378 } 379 380 private int realSize() { 381 return containsNullKey ? size - 1 : size; 382 } 383 384 public void ensureCapacity(final int capacity) { 385 final int needed = arraySize(capacity, f); 386 if (needed > n) 387 rehash(needed); 388 } 389 private void tryCapacity(final long capacity) { 390 final int needed = (int) Math.min( 391 1 << 30, 392 Math.max(2, HashCommon.nextPowerOfTwo((long) Math.ceil(capacity 393 / f)))); 394 if (needed > n) 395 rehash(needed); 396 } 397 protected V removeEntry(final int pos) { 398 final V oldValue = value[pos]; 399 value[pos] = null; 400 size--; 401 fixOrder(pos); 402 shiftKeys(pos); 403 if (size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE) 404 rehash(n / 2); 405 return oldValue; 406 } 407 protected V removeNullEntry() { 408 containsNullKey = false; 409 key[n] = null; 410 final V oldValue = value[n]; 411 value[n] = null; 412 size--; 413 fixOrder(n); 414 if (size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE) 415 rehash(n / 2); 416 return oldValue; 417 } 418 419 /** 420 * Puts the first key in keyArray with the first value in valueArray, then the second in each and so on. 421 * The entries are all appended to the end of the iteration order, unless a key was already present. Then, 422 * its value is changed at the existing position in the iteration order. 423 * If the lengths of the two arrays are not equal, this puts a number of entries equal to the lesser length. 424 * If either array is null, this returns without performing any changes. 425 * @param keyArray an array of K keys that should usually have the same length as valueArray 426 * @param valueArray an array of V values that should usually have the same length as keyArray 427 */ 428 public void putAll(final K[] keyArray, final V[] valueArray) 429 { 430 if(keyArray == null || valueArray == null) 431 return; 432 for (int i = 0; i < keyArray.length && i < valueArray.length; i++) 433 put(keyArray[i], valueArray[i]); 434 435 } 436 437 /** 438 * Puts all key-value pairs in the Map m into this OrderedMap. 439 * The entries are all appended to the end of the iteration order, unless a key was already present. Then, 440 * its value is changed at the existing position in the iteration order. This can take any kind of Map, 441 * including unordered HashMap objects; if the Map does not have stable ordering, the order in which entries 442 * will be appended is not stable either. For this reason, OrderedMap, LinkedHashMap, and TreeMap (or other 443 * SortedMap implementations) will work best when order matters. 444 * @param m a Map that should have the same or compatible K key and V value types; OrderedMap and TreeMap work best 445 */ 446 public void putAll(Map<? extends K, ? extends V> m) { 447 if (f <= .5) 448 ensureCapacity(m.size()); // The resulting map will be sized for 449 // m.size() elements 450 else 451 tryCapacity(size() + m.size()); // The resulting map will be 452 int n = m.size(); 453 final Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m 454 .entrySet().iterator(); 455 if (m instanceof OrderedMap) { 456 Entry<? extends K, ? extends V> e; 457 while (n-- != 0) { 458 e = i.next(); 459 put(e.getKey(), e.getValue()); 460 } 461 } else { 462 Map.Entry<? extends K, ? extends V> e; 463 while (n-- != 0) { 464 e = i.next(); 465 put(e.getKey(), e.getValue()); 466 } 467 } 468 } 469 private int insert(final K k, final V v) { 470 int pos; 471 if (k == null) { 472 if (containsNullKey) 473 return n; 474 containsNullKey = true; 475 pos = n; 476 } else { 477 K curr; 478 final K[] key = this.key; 479 // The starting point. 480 if ((curr = key[pos = (hasher.hash(k)) & mask]) != null) { 481 if (hasher.areEqual(curr, k)) 482 return pos; 483 while ((curr = key[pos = (pos + 1) & mask]) != null) 484 if (hasher.areEqual(curr, k)) 485 return pos; 486 } 487 } 488 key[pos] = k; 489 value[pos] = v; 490 order.add(pos); 491 if (size++ >= maxFill) 492 rehash(arraySize(size + 1, f)); 493 return -1; 494 } 495 private int insertAt(final K k, final V v, final int idx) { 496 int pos; 497 if (k == null) { 498 if (containsNullKey) 499 { 500 fixOrder(n); 501 order.insert(idx, n); 502 return n; 503 } 504 containsNullKey = true; 505 pos = n; 506 } else { 507 K curr; 508 final K[] key = this.key; 509 // The starting point. 510 if ((curr = key[pos = (hasher.hash(k)) & mask]) != null) { 511 if (hasher.areEqual(curr, k)) 512 { 513 fixOrder(pos); 514 order.insert(idx, pos); 515 return pos; 516 } 517 while ((curr = key[pos = (pos + 1) & mask]) != null) 518 if (hasher.areEqual(curr, k)) 519 { 520 fixOrder(pos); 521 order.insert(idx, pos); 522 return pos; 523 } 524 } 525 } 526 key[pos] = k; 527 value[pos] = v; 528 order.insert(idx, pos); 529 if (size++ >= maxFill) 530 rehash(arraySize(size + 1, f)); 531 return -1; 532 } 533 public V put(final K k, final V v) { 534 final int pos = insert(k, v); 535 if (pos < 0) 536 return defRetValue; 537 final V oldValue = value[pos]; 538 value[pos] = v; 539 return oldValue; 540 } 541 public V putAt(final K k, final V v, final int idx) { 542 final int pos = insertAt(k, v, idx); 543 if (pos < 0) 544 return defRetValue; 545 final V oldValue = value[pos]; 546 value[pos] = v; 547 return oldValue; 548 } 549 /** 550 * Shifts left entries with the specified hash code, starting at the 551 * specified position, and empties the resulting free entry. 552 * 553 * @param pos 554 * a starting position. 555 */ 556 protected final void shiftKeys(int pos) { 557 // Shift entries with the same hash. 558 int last, slot; 559 K curr; 560 final K[] key = this.key; 561 for (;;) { 562 pos = ((last = pos) + 1) & mask; 563 for (;;) { 564 if ((curr = key[pos]) == null) { 565 key[last] = null; 566 value[last] = null; 567 return; 568 } 569 slot = (hasher.hash(curr)) 570 & mask; 571 if (last <= pos ? last >= slot || slot > pos : last >= slot 572 && slot > pos) 573 break; 574 pos = (pos + 1) & mask; 575 } 576 key[last] = curr; 577 value[last] = value[pos]; 578 fixOrder(pos, last); 579 } 580 } 581 public V remove(final Object k) { 582 if (k == null) { 583 if (containsNullKey) 584 return removeNullEntry(); 585 return defRetValue; 586 } 587 K curr; 588 final K[] key = this.key; 589 int pos; 590 // The starting point. 591 if ((curr = key[pos = (hasher.hash(k)) & mask]) == null) 592 return defRetValue; 593 if (hasher.areEqual(k, curr)) 594 return removeEntry(pos); 595 while (true) { 596 if ((curr = key[pos = (pos + 1) & mask]) == null) 597 return defRetValue; 598 if (hasher.areEqual(k, curr)) 599 return removeEntry(pos); 600 } 601 } 602 private V setValue(final int pos, final V v) { 603 final V oldValue = value[pos]; 604 value[pos] = v; 605 return oldValue; 606 } 607 /** 608 * Removes the mapping associated with the first key in iteration order. 609 * 610 * @return the value previously associated with the first key in iteration 611 * order. 612 * @throws NoSuchElementException 613 * is this map is empty. 614 */ 615 public V removeFirst() { 616 if (size == 0) 617 throw new NoSuchElementException(); 618 final int pos = order.removeIndex(0); 619 620 size--; 621 final V v = value[pos]; 622 if (pos == n) { 623 containsNullKey = false; 624 key[n] = null; 625 value[n] = null; 626 } else 627 shiftKeys(pos); 628 if (size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE) 629 rehash(n / 2); 630 return v; 631 } 632 /** 633 * Removes the mapping associated with the last key in iteration order. 634 * 635 * @return the value previously associated with the last key in iteration 636 * order. 637 * @throws NoSuchElementException 638 * is this map is empty. 639 */ 640 public V removeLast() { 641 if (size == 0) 642 throw new NoSuchElementException(); 643 final int pos = order.items[order.size-1]; 644 order.pop(); 645 size--; 646 final V v = value[pos]; 647 if (pos == n) { 648 containsNullKey = false; 649 key[n] = null; 650 value[n] = null; 651 } else 652 shiftKeys(pos); 653 if (size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE) 654 rehash(n / 2); 655 return v; 656 } 657 private void moveIndexToFirst(final int i) { 658 if(size <= 1 || order.items[0] == i) 659 return; 660 order.moveToFirst(i); 661 } 662 private void moveIndexToLast(final int i) { 663 if(size <= 1 || order.items[order.size-1] == i) 664 return; 665 order.moveToLast(i); 666 } 667 /** 668 * Returns the value to which the given key is mapped; if the key is 669 * present, it is moved to the first position of the iteration order. 670 * 671 * @param k 672 * the key. 673 * @return the corresponding value, or the 674 * {@linkplain #defaultReturnValue() default return value} if no 675 * value was present for the given key. 676 */ 677 public V getAndMoveToFirst(final K k) { 678 if (k == null) { 679 if (containsNullKey) { 680 moveIndexToFirst(n); 681 return value[n]; 682 } 683 return defRetValue; 684 } 685 K curr; 686 final K[] key = this.key; 687 int pos; 688 // The starting point. 689 if ((curr = key[pos = (hasher.hash(k)) & mask]) == null) 690 return defRetValue; 691 if (hasher.areEqual(k, curr)) { 692 moveIndexToFirst(pos); 693 return value[pos]; 694 } 695 // There's always an unused entry. 696 while (true) { 697 if ((curr = key[pos = (pos + 1) & mask]) == null) 698 return defRetValue; 699 if (hasher.areEqual(k, curr)) { 700 moveIndexToFirst(pos); 701 return value[pos]; 702 } 703 } 704 } 705 /** 706 * Returns the value to which the given key is mapped; if the key is 707 * present, it is moved to the last position of the iteration order. 708 * 709 * @param k the key. 710 * @return the corresponding value, or the 711 * {@linkplain #defaultReturnValue() default return value} if no 712 * value was present for the given key. 713 */ 714 public V getAndMoveToLast(final K k) { 715 if (k == null) { 716 if (containsNullKey) { 717 moveIndexToLast(n); 718 return value[n]; 719 } 720 return defRetValue; 721 } 722 K curr; 723 final K[] key = this.key; 724 int pos; 725 // The starting point. 726 if ((curr = key[pos = (hasher.hash(k)) & mask]) == null) 727 return defRetValue; 728 if (hasher.areEqual(k, curr)) { 729 moveIndexToLast(pos); 730 return value[pos]; 731 } 732 // There's always an unused entry. 733 while (true) { 734 if ((curr = key[pos = (pos + 1) & mask]) == null) 735 return defRetValue; 736 if (hasher.areEqual(k, curr)) { 737 moveIndexToLast(pos); 738 return value[pos]; 739 } 740 } 741 } 742 /** 743 * Adds a pair to the map; if the key is already present, it is moved to the 744 * first position of the iteration order. 745 * 746 * @param k 747 * the key. 748 * @param v 749 * the value. 750 * @return the old value, or the {@linkplain #defaultReturnValue() default 751 * return value} if no value was present for the given key. 752 */ 753 public V putAndMoveToFirst(final K k, final V v) { 754 int pos; 755 if (k == null) { 756 if (containsNullKey) { 757 moveIndexToFirst(n); 758 return setValue(n, v); 759 } 760 containsNullKey = true; 761 pos = n; 762 } else { 763 K curr; 764 final K[] key = this.key; 765 // The starting point. 766 if (!((curr = key[pos = (hasher.hash(k)) & mask]) == null)) { 767 if (hasher.areEqual(curr, k)) { 768 moveIndexToFirst(pos); 769 return setValue(pos, v); 770 } 771 while (!((curr = key[pos = (pos + 1) & mask]) == null)) 772 if (hasher.areEqual(curr, k)) { 773 moveIndexToFirst(pos); 774 return setValue(pos, v); 775 } 776 } 777 } 778 key[pos] = k; 779 value[pos] = v; 780 order.insert(0, pos); 781 if (size++ >= maxFill) 782 rehash(arraySize(size, f)); 783 return defRetValue; 784 } 785 /** 786 * Adds a pair to the map; if the key is already present, it is moved to the 787 * last position of the iteration order. 788 * 789 * @param k 790 * the key. 791 * @param v 792 * the value. 793 * @return the old value, or the {@linkplain #defaultReturnValue() default 794 * return value} if no value was present for the given key. 795 */ 796 public V putAndMoveToLast(final K k, final V v) { 797 int pos; 798 if (k == null) { 799 if (containsNullKey) { 800 moveIndexToLast(n); 801 return setValue(n, v); 802 } 803 containsNullKey = true; 804 pos = n; 805 } else { 806 K curr; 807 final K[] key = this.key; 808 // The starting point. 809 if (!((curr = key[pos = (hasher.hash(k)) & mask]) == null)) { 810 if (hasher.areEqual(curr, k)) { 811 moveIndexToLast(pos); 812 return setValue(pos, v); 813 } 814 while (!((curr = key[pos = (pos + 1) & mask]) == null)) 815 if (hasher.areEqual(curr, k)) { 816 moveIndexToLast(pos); 817 return setValue(pos, v); 818 } 819 } 820 } 821 key[pos] = k; 822 value[pos] = v; 823 if(order.peek() != pos) 824 order.add(pos); 825 if (size++ >= maxFill) 826 rehash(arraySize(size, f)); 827 return defRetValue; 828 } 829 public V get(final Object k) { 830 if (k == null) 831 return containsNullKey ? value[n] : defRetValue; 832 K curr; 833 final K[] key = this.key; 834 int pos; 835 // The starting point. 836 if ((curr = key[pos = (hasher.hash(k)) & mask]) == null) 837 return defRetValue; 838 if (hasher.areEqual(k, curr)) 839 return value[pos]; 840 // There's always an unused entry. 841 while (true) { 842 if ((curr = key[pos = (pos + 1) & mask]) == null) 843 return defRetValue; 844 if (hasher.areEqual(k, curr)) 845 return value[pos]; 846 } 847 } 848 849 850 public V getOrDefault(final Object k, final V defaultValue) { 851 if (k == null) 852 return containsNullKey ? value[n] : defaultValue; 853 K curr; 854 final K[] key = this.key; 855 int pos; 856 // The starting point. 857 if ((curr = key[pos = (hasher.hash(k)) & mask]) == null) 858 return defaultValue; 859 if (hasher.areEqual(k, curr)) 860 return value[pos]; 861 // There's always an unused entry. 862 while (true) { 863 if ((curr = key[pos = (pos + 1) & mask]) == null) 864 return defaultValue; 865 if (hasher.areEqual(k, curr)) 866 return value[pos]; 867 } 868 } 869 870 protected int positionOf(final Object k) { 871 if (k == null) 872 { 873 if(containsNullKey) 874 return n; 875 else 876 return -1; 877 } 878 K curr; 879 final K[] key = this.key; 880 int pos; 881 // The starting point. 882 if ((curr = key[pos = (hasher.hash(k)) & mask]) == null) 883 return -1; 884 if (hasher.areEqual(k, curr)) 885 return pos; 886 // There's always an unused entry. 887 while (true) { 888 if ((curr = key[pos = pos + 1 & mask]) == null) 889 return -1; 890 if (hasher.areEqual(k, curr)) 891 return pos; 892 } 893 } 894 895 /** 896 * Gets the position in the ordering of the given key, though not as efficiently as some data structures can do it 897 * (e.g. {@link Arrangement} can access ordering position very quickly but doesn't store other values on its own). 898 * Returns a value that is at least 0 if it found k, or -1 if k was not present. 899 * @param k a key or possible key that this should find the index of 900 * @return the index of k, if present, or -1 if it is not present in this OrderedMap 901 */ 902 public int indexOf(final Object k) 903 { 904 int pos = positionOf(k); 905 return (pos < 0) ? -1 : order.indexOf(pos); 906 } 907 908 /** 909 * Swaps the positions in the ordering for the given items, if they are both present. Returns true if the ordering 910 * changed as a result of this call, or false if it stayed the same (which can be because left or right was not 911 * present, or because left and right are the same reference (so swapping would do nothing)). 912 * @param left an item that should be present in this OrderedMap 913 * @param right an item that should be present in this OrderedMap 914 * @return true if this OrderedMap changed in ordering as a result of this call, or false otherwise 915 */ 916 public boolean swap(final K left, final K right) 917 { 918 if(left == right) return false; 919 int l = indexOf(left); 920 if(l < 0) return false; 921 int r = indexOf(right); 922 if(r < 0) return false; 923 order.swap(l, r); 924 return true; 925 } 926 /** 927 * Swaps the given indices in the ordering, if they are both valid int indices. Returns true if the ordering 928 * changed as a result of this call, or false if it stayed the same (which can be because left or right referred to 929 * an out-of-bounds index, or because left and right are equal (so swapping would do nothing)). 930 * @param left an index of an item in this OrderedMap, at least 0 and less than {@link #size()} 931 * @param right an index of an item in this OrderedMap, at least 0 and less than {@link #size()} 932 * @return true if this OrderedMap changed in ordering as a result of this call, or false otherwise 933 */ 934 public boolean swapIndices(final int left, final int right) 935 { 936 if(left < 0 || right < 0 || left >= order.size || right >= order.size || left == right) return false; 937 order.swap(left, right); 938 return true; 939 } 940 941 942 public boolean containsKey(final Object k) { 943 if (k == null) 944 return containsNullKey; 945 K curr; 946 final K[] key = this.key; 947 int pos; 948 // The starting point. 949 if ((curr = key[pos = (hasher.hash(k)) & mask]) == null) 950 return false; 951 if (hasher.areEqual(k, curr)) 952 return true; 953 // There's always an unused entry. 954 while (true) { 955 if ((curr = key[pos = (pos + 1) & mask]) == null) 956 return false; 957 if (hasher.areEqual(k, curr)) 958 return true; 959 } 960 } 961 public boolean containsValue(final Object v) { 962 final V[] value = this.value; 963 final K[] key = this.key; 964 if (containsNullKey 965 && (value[n] == null ? v == null : value[n].equals(v))) 966 return true; 967 for (int i = n; i-- != 0;) 968 if (key[i] != null 969 && (value[i] == null ? v == null : value[i].equals(v))) 970 return true; 971 return false; 972 } 973 /* 974 * Removes all elements from this map. 975 * 976 * <P>To increase object reuse, this method does not change the table size. 977 * If you want to reduce the table size, you must use {@link #trim()}. 978 */ 979 public void clear() { 980 if (size == 0) 981 return; 982 size = 0; 983 containsNullKey = false; 984 Arrays.fill(key, null); 985 Arrays.fill(value, null); 986 order.clear(); 987 } 988 989 public int size() { 990 return size; 991 } 992 993 public boolean isEmpty() { 994 return size == 0; 995 } 996 997 /** 998 * The entry class for a OrderedMap does not record key and value, but rather the position in the hash table of the corresponding entry. This is necessary so that calls to 999 * {@link Entry#setValue(Object)} are reflected in the map 1000 */ 1001 final class MapEntry 1002 implements 1003 Entry<K, V> { 1004 // The table index this entry refers to, or -1 if this entry has been 1005 // deleted. 1006 int index; 1007 MapEntry(final int index) { 1008 this.index = index; 1009 } 1010 MapEntry() { 1011 } 1012 public K getKey() { 1013 return key[index]; 1014 } 1015 public V getValue() { 1016 return value[index]; 1017 } 1018 public V setValue(final V v) { 1019 final V oldValue = value[index]; 1020 value[index] = v; 1021 return oldValue; 1022 } 1023 @SuppressWarnings("unchecked") 1024 public boolean equals(final Object o) { 1025 if (!(o instanceof Map.Entry)) 1026 return false; 1027 Map.Entry<K, V> e = (Map.Entry<K, V>) o; 1028 return (key[index] == null 1029 ? e.getKey() == null 1030 : hasher.areEqual(key[index], e.getKey())) 1031 && (value[index] == null 1032 ? e.getValue() == null 1033 : value[index].equals(e.getValue())); 1034 } 1035 public int hashCode() { 1036 return hasher.hash(key[index]) 1037 ^ (value[index] == null ? 0 : value[index].hashCode()); 1038 } 1039 @Override 1040 public String toString() { 1041 return (key[index] == OrderedMap.this ? "(this collection)" : String.valueOf(key[index])) 1042 + "=>" 1043 + (value[index] == OrderedMap.this ? "(this collection)" : String.valueOf(value[index])); 1044 } 1045 } 1046 1047 /** 1048 * Modifies the ordering so that the given entry is removed. This method will complete in linear time. 1049 * 1050 * @param i the index of an entry. 1051 * @return the iteration-order index of the removed entry 1052 */ 1053 protected int fixOrder(final int i) { 1054 if (size == 0) { 1055 order.clear(); 1056 return -1; 1057 } 1058 return order.removeValue(i); 1059 } 1060 1061 /** 1062 * Modifies the ordering for a shift from s to d. 1063 * <br> 1064 * This method will complete in linear time unless the source position is first or last. 1065 * 1066 * @param s the source position. 1067 * @param d the destination position. 1068 */ 1069 protected void fixOrder(int s, int d) { 1070 if(size == 0) 1071 return; 1072 if (size == 1 || order.items[0] == s) { 1073 order.set(0, d); 1074 } 1075 else if (order.items[order.size-1] == s) { 1076 order.set(order.size - 1, d); 1077 } 1078 else 1079 { 1080 order.set(order.indexOf(s), d); 1081 } 1082 } 1083 1084 /** 1085 * Returns the first key of this map in iteration order. 1086 * 1087 * @return the first key in iteration order. 1088 */ 1089 public K firstKey() { 1090 if (size == 0) 1091 throw new NoSuchElementException(); 1092 return key[order.items[0]]; 1093 } 1094 /** 1095 * Returns the last key of this map in iteration order. 1096 * 1097 * @return the last key in iteration order. 1098 */ 1099 public K lastKey() { 1100 if (size == 0) 1101 throw new NoSuchElementException(); 1102 return key[order.items[order.size-1]]; 1103 } 1104 public Comparator<? super K> comparator() { 1105 return null; 1106 } 1107 public SortedMap<K, V> tailMap(K from) { 1108 throw new UnsupportedOperationException(); 1109 } 1110 public SortedMap<K, V> headMap(K to) { 1111 throw new UnsupportedOperationException(); 1112 } 1113 public SortedMap<K, V> subMap(K from, K to) { 1114 throw new UnsupportedOperationException(); 1115 } 1116 /** 1117 * A list iterator over a OrderedMap. 1118 * 1119 * <P> 1120 * This class provides a list iterator over a OrderedMap. The 1121 * constructor runs in constant time. 1122 */ 1123 private class MapIterator { 1124 /** 1125 * The entry that will be returned by the next call to 1126 * {@link java.util.ListIterator#previous()} (or <code>null</code> if no 1127 * previous entry exists). 1128 */ 1129 int prev = -1; 1130 /** 1131 * The entry that will be returned by the next call to 1132 * {@link java.util.ListIterator#next()} (or <code>null</code> if no 1133 * next entry exists). 1134 */ 1135 int next; 1136 /** 1137 * The last entry that was returned (or -1 if we did not iterate or used 1138 * {@link java.util.Iterator#remove()}). 1139 */ 1140 int curr = -1; 1141 /** 1142 * The current index (in the sense of a {@link java.util.ListIterator}). 1143 * Note that this value is not meaningful when this iterator has been 1144 * created using the nonempty constructor. 1145 */ 1146 int index; 1147 private MapIterator() { 1148 next = size == 0 ? -1 : order.items[0]; 1149 index = 0; 1150 } 1151 public boolean hasNext() { 1152 return next != -1; 1153 } 1154 public boolean hasPrevious() { 1155 return prev != -1; 1156 } 1157 private void ensureIndexKnown() { 1158 if (index >= 0) 1159 return; 1160 if (prev == -1) { 1161 index = 0; 1162 return; 1163 } 1164 if (next == -1) { 1165 index = size; 1166 return; 1167 } 1168 index = 0; 1169 } 1170 public int nextIndex() { 1171 ensureIndexKnown(); 1172 return index + 1; 1173 } 1174 public int previousIndex() { 1175 ensureIndexKnown(); 1176 return index - 1; 1177 } 1178 public int nextEntry() { 1179 if (!hasNext()) 1180 throw new NoSuchElementException(); 1181 curr = next; 1182 if(++index >= order.size) 1183 next = -1; 1184 else 1185 next = order.get(index);//(int) link[curr]; 1186 prev = curr; 1187 return curr; 1188 } 1189 public int previousEntry() { 1190 if (!hasPrevious()) 1191 throw new NoSuchElementException(); 1192 curr = prev; 1193 if(--index < 1) 1194 prev = -1; 1195 else 1196 prev = order.get(index - 1); 1197 next = curr; 1198 return curr; 1199 } 1200 public void remove() { 1201 ensureIndexKnown(); 1202 if (curr == -1) 1203 throw new IllegalStateException(); 1204 if (curr == prev) { 1205 /* 1206 * If the last operation was a next(), we are removing an entry 1207 * that precedes the current index, and thus we must decrement 1208 * it. 1209 */ 1210 if(--index >= 1) 1211 prev = order.get(index - 1); //(int) (link[curr] >>> 32); 1212 else 1213 prev = -1; 1214 } else { 1215 if(index < order.size - 1) 1216 next = order.get(index + 1); 1217 else 1218 next = -1; 1219 } 1220 order.removeIndex(index); 1221 size--; 1222 int last, slot, pos = curr; 1223 curr = -1; 1224 if (pos == n) { 1225 containsNullKey = false; 1226 key[n] = null; 1227 value[n] = null; 1228 } else { 1229 K curr; 1230 final K[] key = OrderedMap.this.key; 1231 // We have to horribly duplicate the shiftKeys() code because we 1232 // need to update next/prev. 1233 for (;;) { 1234 pos = ((last = pos) + 1) & mask; 1235 for (;;) { 1236 if ((curr = key[pos]) == null) { 1237 key[last] = null; 1238 value[last] = null; 1239 return; 1240 } 1241 slot = (hasher.hash(curr)) & mask; 1242 if (last <= pos 1243 ? last >= slot || slot > pos 1244 : last >= slot && slot > pos) 1245 break; 1246 pos = (pos + 1) & mask; 1247 } 1248 key[last] = curr; 1249 value[last] = value[pos]; 1250 if (next == pos) 1251 next = last; 1252 if (prev == pos) 1253 prev = last; 1254 fixOrder(pos, last); 1255 } 1256 } 1257 } 1258 public int skip(final int n) { 1259 int i = n; 1260 while (i-- != 0 && hasNext()) 1261 nextEntry(); 1262 return n - i - 1; 1263 } 1264 public int back(final int n) { 1265 int i = n; 1266 while (i-- != 0 && hasPrevious()) 1267 previousEntry(); 1268 return n - i - 1; 1269 } 1270 } 1271 private class EntryIterator extends MapIterator 1272 implements 1273 Iterator<Entry<K, V>>, Serializable { 1274 private static final long serialVersionUID = 0L; 1275 1276 private MapEntry entry; 1277 public EntryIterator() { 1278 } 1279 public MapEntry next() { 1280 return entry = new MapEntry(nextEntry()); 1281 } 1282 public MapEntry previous() { 1283 return entry = new MapEntry(previousEntry()); 1284 } 1285 @Override 1286 public void remove() { 1287 super.remove(); 1288 entry.index = -1; // You cannot use a deleted entry. 1289 } 1290 public void set(Entry<K, V> ok) { 1291 throw new UnsupportedOperationException(); 1292 } 1293 public void add(Entry<K, V> ok) { 1294 throw new UnsupportedOperationException(); 1295 } 1296 } 1297 1298 public final class MapEntrySet 1299 implements Cloneable, SortedSet<Entry<K, V>>, Set<Entry<K, V>>, Collection<Entry<K, V>>, Serializable { 1300 private static final long serialVersionUID = 0L; 1301 public EntryIterator iterator() { 1302 return new EntryIterator(); 1303 } 1304 public Comparator<? super Entry<K, V>> comparator() { 1305 return null; 1306 } 1307 public SortedSet<Entry<K, V>> subSet( 1308 Entry<K, V> fromElement, 1309 Entry<K, V> toElement) { 1310 throw new UnsupportedOperationException(); 1311 } 1312 public SortedSet<Entry<K, V>> headSet( 1313 Entry<K, V> toElement) { 1314 throw new UnsupportedOperationException(); 1315 } 1316 public SortedSet<Entry<K, V>> tailSet( 1317 Entry<K, V> fromElement) { 1318 throw new UnsupportedOperationException(); 1319 } 1320 public Entry<K, V> first() { 1321 if (size == 0) 1322 throw new NoSuchElementException(); 1323 return new MapEntry(order.items[0]); 1324 } 1325 public Entry<K, V> last() { 1326 if (size == 0) 1327 throw new NoSuchElementException(); 1328 return new MapEntry(order.items[order.size-1]); 1329 } 1330 @SuppressWarnings("unchecked") 1331 public boolean contains(final Object o) { 1332 if (!(o instanceof Map.Entry)) 1333 return false; 1334 final Map.Entry<?, ?> e = (Map.Entry<?, ?>) o; 1335 final K k = (K) e.getKey(); 1336 final V v = (V) e.getValue(); 1337 if (k == null) 1338 return containsNullKey 1339 && (value[n] == null ? v == null : value[n] 1340 .equals(v)); 1341 K curr; 1342 final K[] key = OrderedMap.this.key; 1343 int pos; 1344 // The starting point. 1345 if ((curr = key[pos = (hasher.hash(k)) & mask]) == null) 1346 return false; 1347 if (hasher.areEqual(k, curr)) 1348 return value[pos] == null ? v == null : value[pos] 1349 .equals(v); 1350 // There's always an unused entry. 1351 while (true) { 1352 if ((curr = key[pos = (pos + 1) & mask]) == null) 1353 return false; 1354 if (hasher.areEqual(k, curr)) 1355 return value[pos] == null ? v == null : value[pos] 1356 .equals(v); 1357 } 1358 } 1359 @SuppressWarnings("unchecked") 1360 public boolean remove(final Object o) { 1361 if (!(o instanceof Map.Entry)) 1362 return false; 1363 final Map.Entry<?, ?> e = (Map.Entry<?, ?>) o; 1364 final K k = (K) e.getKey(); 1365 final V v = (V) e.getValue(); 1366 if (k == null) { 1367 if (containsNullKey 1368 && (value[n] == null ? v == null : value[n] 1369 .equals(v))) { 1370 removeNullEntry(); 1371 return true; 1372 } 1373 return false; 1374 } 1375 K curr; 1376 final K[] key = OrderedMap.this.key; 1377 int pos; 1378 // The starting point. 1379 if ((curr = key[pos = (hasher.hash(k)) & mask]) == null) 1380 return false; 1381 if (hasher.areEqual(curr, k)) { 1382 if (value[pos] == null ? v == null : value[pos] 1383 .equals(v)) { 1384 removeEntry(pos); 1385 return true; 1386 } 1387 return false; 1388 } 1389 while (true) { 1390 if ((curr = key[pos = (pos + 1) & mask]) == null) 1391 return false; 1392 if (hasher.areEqual(curr, k)) { 1393 if (value[pos] == null ? v == null : value[pos] 1394 .equals(v)) { 1395 removeEntry(pos); 1396 return true; 1397 } 1398 } 1399 } 1400 } 1401 public int size() { 1402 return size; 1403 } 1404 public void clear() { 1405 OrderedMap.this.clear(); 1406 } 1407 1408 @Override 1409 public boolean equals(final Object o) { 1410 if (o == this) 1411 return true; 1412 if (!(o instanceof Set)) 1413 return false; 1414 Set<?> s = (Set<?>) o; 1415 return s.size() == size() && containsAll(s); 1416 } 1417 1418 public Object[] toArray() { 1419 final Object[] a = new Object[size()]; 1420 objectUnwrap(iterator(), a); 1421 return a; 1422 } 1423 1424 @SuppressWarnings("unchecked") 1425 public <T> T[] toArray(T[] a) { 1426 if (a == null || a.length < size()) a = (T[]) new Object[size()]; 1427 objectUnwrap(iterator(), a); 1428 return a; 1429 } 1430 1431 /** 1432 * Unsupported. 1433 * 1434 * @param c ignored 1435 * @return nothing, throws UnsupportedOperationException 1436 * @throws UnsupportedOperationException always 1437 */ 1438 public boolean addAll(Collection<? extends Entry<K, V>> c) { 1439 throw new UnsupportedOperationException("addAll not supported"); 1440 } 1441 1442 /** 1443 * Unsupported. 1444 * 1445 * @param k ignored 1446 * @return nothing, throws UnsupportedOperationException 1447 * @throws UnsupportedOperationException always 1448 */ 1449 public boolean add(Entry<K, V> k) { 1450 throw new UnsupportedOperationException("add not supported"); 1451 } 1452 1453 /** 1454 * Checks whether this collection contains all elements from the given 1455 * collection. 1456 * 1457 * @param c a collection. 1458 * @return <code>true</code> if this collection contains all elements of the 1459 * argument. 1460 */ 1461 public boolean containsAll(Collection<?> c) { 1462 int n = c.size(); 1463 final Iterator<?> i = c.iterator(); 1464 while (n-- != 0) 1465 if (!contains(i.next())) 1466 return false; 1467 return true; 1468 } 1469 1470 /** 1471 * Retains in this collection only elements from the given collection. 1472 * 1473 * @param c a collection. 1474 * @return <code>true</code> if this collection changed as a result of the 1475 * call. 1476 */ 1477 public boolean retainAll(Collection<?> c) { 1478 boolean retVal = false; 1479 int n = size(); 1480 final Iterator<?> i = iterator(); 1481 while (n-- != 0) { 1482 if (!c.contains(i.next())) { 1483 i.remove(); 1484 retVal = true; 1485 } 1486 } 1487 return retVal; 1488 } 1489 1490 /** 1491 * Remove from this collection all elements in the given collection. If the 1492 * collection is an instance of this class, it uses faster iterators. 1493 * 1494 * @param c a collection. 1495 * @return <code>true</code> if this collection changed as a result of the 1496 * call. 1497 */ 1498 public boolean removeAll(Collection<?> c) { 1499 boolean retVal = false; 1500 int n = c.size(); 1501 final Iterator<?> i = c.iterator(); 1502 while (n-- != 0) 1503 if (remove(i.next())) 1504 retVal = true; 1505 return retVal; 1506 } 1507 1508 public boolean isEmpty() { 1509 return size() == 0; 1510 } 1511 1512 @Override 1513 public String toString() { 1514 final StringBuilder s = new StringBuilder(); 1515 final EntryIterator i = iterator(); 1516 int n = size(); 1517 MapEntry k; 1518 boolean first = true; 1519 s.append("{"); 1520 while (n-- != 0) { 1521 if (first) 1522 first = false; 1523 else 1524 s.append(", "); 1525 k = i.next(); 1526 s.append(key[k.index] == OrderedMap.this ? "(this collection)" : String.valueOf(key[k.index])) 1527 .append("=>") 1528 .append(value[k.index] == OrderedMap.this ? "(this collection)" : String.valueOf(value[k.index])); 1529 } 1530 s.append("}"); 1531 return s.toString(); 1532 } 1533 1534 } 1535 1536 @Override 1537 public SortedSet<Entry<K,V>> entrySet() { 1538 if (entries == null) entries = new MapEntrySet(); 1539 return entries; 1540 } 1541 1542 /** 1543 * An iterator on keys. 1544 * <p> 1545 * <P>We simply override the {@link ListIterator#next()}/{@link ListIterator#previous()} methods (and possibly their type-specific counterparts) so that they return keys 1546 * instead of entries. 1547 */ 1548 public final class KeyIterator extends MapIterator implements Iterator<K>, Serializable { 1549 private static final long serialVersionUID = 0L; 1550 public K previous() { 1551 return key[previousEntry()]; 1552 } 1553 public void set(K k) { 1554 throw new UnsupportedOperationException(); 1555 } 1556 public void add(K k) { 1557 throw new UnsupportedOperationException(); 1558 } 1559 public KeyIterator() {} 1560 public K next() { 1561 return key[nextEntry()]; 1562 } 1563 public void remove() { super.remove(); } 1564 } 1565 1566 public final class KeySet implements SortedSet<K>, Serializable { 1567 private static final long serialVersionUID = 0L; 1568 1569 public KeyIterator iterator() { 1570 return new KeyIterator(); 1571 } 1572 1573 public int size() { 1574 return size; 1575 } 1576 1577 public void clear() { 1578 OrderedMap.this.clear(); 1579 } 1580 1581 public K first() { 1582 if (size == 0) throw new NoSuchElementException(); 1583 return key[order.items[0]]; 1584 } 1585 1586 public K last() { 1587 if (size == 0) throw new NoSuchElementException(); 1588 return key[order.items[order.size-1]]; 1589 } 1590 1591 public Comparator<K> comparator() { 1592 return null; 1593 } 1594 1595 public final SortedSet<K> tailSet(K from) { 1596 throw new UnsupportedOperationException(); 1597 } 1598 1599 public final SortedSet<K> headSet(K to) { 1600 throw new UnsupportedOperationException(); 1601 } 1602 1603 public final SortedSet<K> subSet(K from, K to) { 1604 throw new UnsupportedOperationException(); 1605 } 1606 1607 @SuppressWarnings("unchecked") 1608 @Override 1609 public <T> T[] toArray(T[] a) { 1610 if (a == null || a.length < size()) a = (T[]) new Object[size()]; 1611 unwrap(iterator(), a); 1612 return a; 1613 } 1614 1615 /** 1616 * Always throws an UnsupportedOperationException 1617 */ 1618 public boolean remove(Object ok) { 1619 throw new UnsupportedOperationException("Cannot remove from the key set directly"); 1620 } 1621 1622 /** 1623 * Always throws an UnsupportedOperationException 1624 */ 1625 public boolean add(final K o) { 1626 throw new UnsupportedOperationException("Cannot add to the key set directly"); 1627 } 1628 1629 /** 1630 * Delegates to the corresponding type-specific method. 1631 */ 1632 public boolean contains(final Object o) { 1633 return containsKey(o); 1634 } 1635 1636 /** 1637 * Checks whether this collection contains all elements from the given type-specific collection. 1638 * 1639 * @param c a type-specific collection. 1640 * @return <code>true</code> if this collection contains all elements of the argument. 1641 */ 1642 public boolean containsAll(Collection<?> c) { 1643 final Iterator<?> i = c.iterator(); 1644 int n = c.size(); 1645 while (n-- != 0) 1646 if (!contains(i.next())) return false; 1647 return true; 1648 } 1649 1650 /** 1651 * Retains in this collection only elements from the given type-specific collection. 1652 * 1653 * @param c a type-specific collection. 1654 * @return <code>true</code> if this collection changed as a result of the call. 1655 */ 1656 public boolean retainAll(Collection<?> c) { 1657 boolean retVal = false; 1658 int n = size(); 1659 final Iterator<?> i = iterator(); 1660 while (n-- != 0) { 1661 if (!c.contains(i.next())) { 1662 i.remove(); 1663 retVal = true; 1664 } 1665 } 1666 return retVal; 1667 } 1668 1669 /** 1670 * Remove from this collection all elements in the given type-specific collection. 1671 * 1672 * @param c a type-specific collection. 1673 * @return <code>true</code> if this collection changed as a result of the call. 1674 */ 1675 public boolean removeAll(Collection<?> c) { 1676 boolean retVal = false; 1677 int n = c.size(); 1678 final Iterator<?> i = c.iterator(); 1679 while (n-- != 0) 1680 if (remove(i.next())) retVal = true; 1681 return false; 1682 } 1683 1684 public Object[] toArray() { 1685 final Object[] a = new Object[size()]; 1686 objectUnwrap(iterator(), a); 1687 return a; 1688 } 1689 1690 /** 1691 * Adds all elements of the given collection to this collection. 1692 * 1693 * @param c a collection. 1694 * @return <code>true</code> if this collection changed as a result of the call. 1695 */ 1696 public boolean addAll(Collection<? extends K> c) { 1697 boolean retVal = false; 1698 final Iterator<? extends K> i = c.iterator(); 1699 int n = c.size(); 1700 while (n-- != 0) 1701 if (add(i.next())) retVal = true; 1702 return false; 1703 } 1704 1705 @Override 1706 public boolean equals(final Object o) { 1707 if (o == this) 1708 return true; 1709 if (!(o instanceof Set)) 1710 return false; 1711 Set<?> s = (Set<?>) o; 1712 if (s.size() != size()) 1713 return false; 1714 return containsAll(s); 1715 } 1716 /** 1717 * Unwraps an iterator into an array starting at a given offset for a given number of elements. 1718 * <p> 1719 * <P>This method iterates over the given type-specific iterator and stores the elements returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>. The 1720 * number of actually unwrapped elements is returned (it may be less than <code>max</code> if the iterator emits less than <code>max</code> elements). 1721 * 1722 * @param i a type-specific iterator. 1723 * @param array an array to contain the output of the iterator. 1724 * @param offset the first element of the array to be returned. 1725 * @param max the maximum number of elements to unwrap. 1726 * @return the number of elements unwrapped. 1727 */ 1728 public int unwrap(final KeyIterator i, final Object[] array, int offset, final int max) { 1729 if (max < 0) throw new IllegalArgumentException("The maximum number of elements (" + max + ") is negative"); 1730 if (offset < 0 || offset + max > array.length) throw new IllegalArgumentException(); 1731 int j = max; 1732 while (j-- != 0 && i.hasNext()) 1733 array[offset++] = i.next(); 1734 return max - j - 1; 1735 } 1736 1737 /** 1738 * Unwraps an iterator into an array. 1739 * <p> 1740 * <P>This method iterates over the given type-specific iterator and stores the elements returned in the given array. The iteration will stop when the iterator has no more elements or when the end 1741 * of the array has been reached. 1742 * 1743 * @param i a type-specific iterator. 1744 * @param array an array to contain the output of the iterator. 1745 * @return the number of elements unwrapped. 1746 */ 1747 public int unwrap(final KeyIterator i, final Object[] array) { 1748 return unwrap(i, array, 0, array.length); 1749 } 1750 1751 public boolean isEmpty() { 1752 return size() == 0; 1753 } 1754 1755 @Override 1756 public String toString() { 1757 final StringBuilder s = new StringBuilder(); 1758 int n = size(); 1759 boolean first = true; 1760 s.append("{"); 1761 for (int i = 0; i < n; i++) { 1762 if (first) first = false; 1763 else s.append(", "); 1764 K k = keyAt(i); 1765 s.append(k == OrderedMap.this ? "(this collection)" : String.valueOf(k)); 1766 } 1767 s.append("}"); 1768 return s.toString(); 1769 } 1770 } 1771 1772 public SortedSet<K> keySet() { 1773 if (keys == null) keys = new KeySet(); 1774 return keys; 1775 } 1776 1777 public OrderedSet<K> keysAsOrderedSet() 1778 { 1779 OrderedSet<K> os = new OrderedSet<>(size, f, hasher); 1780 for (int i = 0; i < size; i++) { 1781 os.add(keyAt(i)); 1782 } 1783 return os; 1784 } 1785 1786 /** 1787 * An iterator on values. 1788 * <p> 1789 * <P>We simply override the {@link ListIterator#next()}/{@link ListIterator#previous()} methods (and possibly their type-specific counterparts) so that they return values 1790 * instead of entries. 1791 */ 1792 public final class ValueIterator extends MapIterator implements ListIterator<V>, Serializable { 1793 private static final long serialVersionUID = 0L; 1794 1795 public V previous() { 1796 return value[previousEntry()]; 1797 } 1798 public void set(V v) { 1799 throw new UnsupportedOperationException(); 1800 } 1801 public void add(V v) { 1802 throw new UnsupportedOperationException(); 1803 } 1804 public ValueIterator() {} 1805 public V next() { 1806 return value[nextEntry()]; 1807 } 1808 public void remove() { super.remove(); } 1809 } 1810 public final class ValueCollection extends AbstractCollection<V> implements Serializable 1811 { 1812 private static final long serialVersionUID = 0L; 1813 public ValueIterator iterator() { 1814 return new ValueIterator(); 1815 } 1816 public int size() { 1817 return size; 1818 } 1819 public boolean contains(Object v) { 1820 return containsValue(v); 1821 } 1822 public void clear() { 1823 OrderedMap.this.clear(); 1824 } 1825 } 1826 public Collection<V> values() { 1827 if (values == null) values = new ValueCollection(); 1828 return values; 1829 } 1830 1831 public ArrayList<V> valuesAsList() 1832 { 1833 ArrayList<V> ls = new ArrayList<>(size); 1834 for (int i = 0; i < size; i++) { 1835 ls.add(getAt(i)); 1836 } 1837 return ls; 1838 } 1839 1840 /** 1841 * Rehashes the map, making the table as small as possible. 1842 * <p> 1843 * <P>This method rehashes the table to the smallest size satisfying the load factor. It can be used when the set will not be changed anymore, so to optimize access speed and size. 1844 * <p> 1845 * <P>If the table size is already the minimum possible, this method does nothing. 1846 * 1847 * @return true if there was enough memory to trim the map. 1848 * @see #trim(int) 1849 */ 1850 public boolean trim() { 1851 final int l = arraySize(size, f); 1852 if (l >= n || size > maxFill(l, f)) return true; 1853 try { 1854 rehash(l); 1855 } catch (Exception cantDoIt) { 1856 return false; 1857 } 1858 return true; 1859 } 1860 1861 /** 1862 * Rehashes this map if the table is too large. 1863 * <p> 1864 * <P>Let <var>N</var> be the smallest table size that can hold <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current table size is smaller than or equal to 1865 * <var>N</var>, this method does nothing. Otherwise, it rehashes this map in a table of size <var>N</var>. 1866 * <p> 1867 * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a map} leaves the table size untouched. If you are reusing a map many times, you can call this method with a typical 1868 * size to avoid keeping around a very large table just because of a few large transient maps. 1869 * 1870 * @param n the threshold for the trimming. 1871 * @return true if there was enough memory to trim the map. 1872 * @see #trim() 1873 */ 1874 public boolean trim(final int n) { 1875 final int l = HashCommon.nextPowerOfTwo((int) Math.ceil(n / f)); 1876 if (l >= n || size > maxFill(l, f)) return true; 1877 try { 1878 rehash(l); 1879 } catch (Exception cantDoIt) { 1880 return false; 1881 } 1882 return true; 1883 } 1884 1885 /** 1886 * Rehashes the map. 1887 * 1888 * <P> 1889 * This method implements the basic rehashing strategy, and may be overriden 1890 * by subclasses implementing different rehashing strategies (e.g., 1891 * disk-based rehashing). However, you should not override this method 1892 * unless you understand the internal workings of this class. 1893 * 1894 * @param newN 1895 * the new size 1896 */ 1897 1898 @SuppressWarnings("unchecked") 1899 protected void rehash(final int newN) { 1900 final K[] key = this.key; 1901 final V[] value = this.value; 1902 final int mask = newN - 1; 1903 final K[] newKey = (K[]) new Object[newN + 1]; 1904 final V[] newValue = (V[]) new Object[newN + 1]; 1905 final int sz = order.size; 1906 K k; 1907 int i, pos; 1908 final int[] oi = order.items; 1909 for (int q = 0; q < sz; q++) { 1910 i = oi[q]; 1911 if ((k = key[i]) == null) 1912 pos = newN; 1913 else { 1914 pos = (hasher.hash(k)) & mask; 1915 while (newKey[pos] != null) 1916 pos = (pos + 1) & mask; 1917 } 1918 newKey[pos] = k; 1919 newValue[pos] = value[i]; 1920 oi[q] = pos; 1921 } 1922 n = newN; 1923 this.mask = mask; 1924 maxFill = maxFill(n, f); 1925 this.key = newKey; 1926 this.value = newValue; 1927 } 1928 /* 1929 @SuppressWarnings("unchecked") 1930 protected void rehash(final int newN) { 1931 final K key[] = this.key; 1932 final V value[] = this.value; 1933 final int mask = newN - 1; // Note that this is used by the hashing 1934 // macro 1935 final K newKey[] = (K[]) new Object[newN + 1]; 1936 final V newValue[] = (V[]) new Object[newN + 1]; 1937 int i = first, prev = -1, newPrev = -1, t, pos; 1938 final long link[] = this.link; 1939 final long newLink[] = new long[newN + 1]; 1940 first = -1; 1941 for (int j = size; j-- != 0;) { 1942 if (((key[i]) == null)) 1943 pos = newN; 1944 else { 1945 pos = (((key[i]).hashCode())) & mask; 1946 while (!((newKey[pos]) == null)) 1947 pos = (pos + 1) & mask; 1948 } 1949 newKey[pos] = key[i]; 1950 newValue[pos] = value[i]; 1951 if (prev != -1) { 1952 newLink[newPrev] ^= ((newLink[newPrev] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL); 1953 newLink[pos] ^= ((newLink[pos] ^ ((newPrev & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L); 1954 newPrev = pos; 1955 } else { 1956 newPrev = first = pos; 1957 // Special case of SET(newLink[ pos ], -1, -1); 1958 newLink[pos] = -1L; 1959 } 1960 t = i; 1961 i = (int) link[i]; 1962 prev = t; 1963 } 1964 this.link = newLink; 1965 this.last = newPrev; 1966 if (newPrev != -1) 1967 // Special case of SET_NEXT( newLink[ newPrev ], -1 ); 1968 newLink[newPrev] |= -1 & 0xFFFFFFFFL; 1969 n = newN; 1970 this.mask = mask; 1971 maxFill = maxFill(n, f); 1972 this.key = newKey; 1973 this.value = newValue; 1974 } 1975 */ 1976 /** 1977 * Returns a deep copy of this map. 1978 * 1979 * <P> 1980 * This method performs a deep copy of this OrderedMap; the data stored in the 1981 * map, however, is not cloned. Note that this makes a difference only for 1982 * object keys. 1983 * 1984 * @return a deep copy of this map. 1985 */ 1986 @SuppressWarnings("unchecked") 1987 @GwtIncompatible 1988 public OrderedMap<K, V> clone() { 1989 OrderedMap<K, V> c; 1990 try { 1991 c = new OrderedMap<>(hasher); 1992 c.key = (K[]) new Object[n + 1]; 1993 System.arraycopy(key, 0, c.key, 0, n + 1); 1994 c.value = (V[]) new Object[n + 1]; 1995 System.arraycopy(value, 0, c.value, 0, n + 1); 1996 c.order = (IntVLA) order.clone(); 1997 return c; 1998 } catch (Exception cantHappen) { 1999 throw new UnsupportedOperationException(cantHappen + (cantHappen.getMessage() != null ? 2000 "; " + cantHappen.getMessage() : "")); 2001 } 2002 } 2003 /** 2004 * Returns a hash code for this map. 2005 * 2006 * This method overrides the generic method provided by the superclass. 2007 * Since <code>equals()</code> is not overriden, it is important that the 2008 * value returned by this method is the same value as the one returned by 2009 * the overriden method. 2010 * 2011 * @return a hash code for this map. 2012 */ 2013 public int hashCode() { 2014 int h = 0; 2015 for (int j = realSize(), i = 0, t = 0; j-- != 0;) { 2016 while (key[i] == null) 2017 i++; 2018 if (this != key[i]) 2019 t = hasher.hash(key[i]); 2020 if (this != value[i]) 2021 t ^= value[i] == null ? 0 : value[i].hashCode(); 2022 h += t; 2023 i++; 2024 } 2025 // Zero / null keys have hash zero. 2026 if (containsNullKey) 2027 h += value[n] == null ? 0 : value[n].hashCode(); 2028 return h; 2029 } 2030 2031 public long hash64() 2032 { 2033 return 31L * (31L * CrossHash.hash64(key) + CrossHash.hash64(value)) + size; 2034 } 2035 /** 2036 * Returns the maximum number of entries that can be filled before rehashing. 2037 * 2038 * @param n the size of the backing array. 2039 * @param f the load factor. 2040 * @return the maximum number of entries before rehashing. 2041 */ 2042 public static int maxFill(final int n, final float f) { 2043 /* We must guarantee that there is always at least 2044 * one free entry (even with pathological load factors). */ 2045 return Math.min((int)(n * f + 0.99999994f), n - 1); 2046 } 2047 2048 /** 2049 * Returns the least power of two smaller than or equal to 2<sup>30</sup> and larger than or equal to <code>Math.ceil( expected / f )</code>. 2050 * 2051 * @param expected the expected number of elements in a hash table. 2052 * @param f the load factor. 2053 * @return the minimum possible size for a backing array. 2054 * @throws IllegalArgumentException if the necessary size is larger than 2<sup>30</sup>. 2055 */ 2056 public static int arraySize(final int expected, final float f) { 2057 final long s = Math.max(2, HashCommon.nextPowerOfTwo((long) Math.ceil(expected / f))); 2058 if (s > (1 << 30)) 2059 throw new IllegalArgumentException("Too large (" + expected + " expected elements with load factor " + f + ")"); 2060 return (int) s; 2061 } 2062 2063 /** 2064 * Unwraps an iterator into an array starting at a given offset for a given number of elements. 2065 * <p> 2066 * <P>This method iterates over the given type-specific iterator and stores the elements returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>. The 2067 * number of actually unwrapped elements is returned (it may be less than <code>max</code> if the iterator emits less than <code>max</code> elements). 2068 * 2069 * @param i a type-specific iterator. 2070 * @param array an array to contain the output of the iterator. 2071 * @param offset the first element of the array to be returned. 2072 * @param max the maximum number of elements to unwrap. 2073 * @return the number of elements unwrapped. 2074 */ 2075 protected int unwrap(final ValueIterator i, final Object[] array, int offset, final int max) { 2076 if (max < 0) throw new IllegalArgumentException("The maximum number of elements (" + max + ") is negative"); 2077 if (offset < 0 || offset + max > array.length) throw new IllegalArgumentException(); 2078 int j = max; 2079 while (j-- != 0 && i.hasNext()) 2080 array[offset++] = i.next(); 2081 return max - j - 1; 2082 } 2083 2084 /** 2085 * Unwraps an iterator into an array. 2086 * <p> 2087 * <P>This method iterates over the given type-specific iterator and stores the elements returned in the given array. The iteration will stop when the iterator has no more elements or when the end 2088 * of the array has been reached. 2089 * 2090 * @param i a type-specific iterator. 2091 * @param array an array to contain the output of the iterator. 2092 * @return the number of elements unwrapped. 2093 */ 2094 protected int unwrap(final ValueIterator i, final Object[] array) { 2095 return unwrap(i, array, 0, array.length); 2096 } 2097 2098 2099 /** Unwraps an iterator into an array starting at a given offset for a given number of elements. 2100 * 2101 * <P>This method iterates over the given type-specific iterator and stores the elements returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>. The 2102 * number of actually unwrapped elements is returned (it may be less than <code>max</code> if the iterator emits less than <code>max</code> elements). 2103 * 2104 * @param i a type-specific iterator. 2105 * @param array an array to contain the output of the iterator. 2106 * @param offset the first element of the array to be returned. 2107 * @param max the maximum number of elements to unwrap. 2108 * @return the number of elements unwrapped. */ 2109 protected static <K> int objectUnwrap(final Iterator<? extends K> i, final K[] array, int offset, final int max ) { 2110 if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" ); 2111 if ( offset < 0 || offset + max > array.length ) throw new IllegalArgumentException(); 2112 int j = max; 2113 while ( j-- != 0 && i.hasNext() ) 2114 array[ offset++ ] = i.next(); 2115 return max - j - 1; 2116 } 2117 2118 /** Unwraps an iterator into an array. 2119 * 2120 * <P>This method iterates over the given type-specific iterator and stores the elements returned in the given array. The iteration will stop when the iterator has no more elements or when the end 2121 * of the array has been reached. 2122 * 2123 * @param i a type-specific iterator. 2124 * @param array an array to contain the output of the iterator. 2125 * @return the number of elements unwrapped. */ 2126 protected static <K> int objectUnwrap(final Iterator<? extends K> i, final K[] array) { 2127 return objectUnwrap(i, array, 0, array.length ); 2128 } 2129 2130 @Override 2131 public String toString() { 2132 final StringBuilder s = new StringBuilder(); 2133 int n = size(), i = 0; 2134 boolean first = true; 2135 K k; 2136 V v; 2137 s.append("OrderedMap{"); 2138 while (i < n) { 2139 if (first) first = false; 2140 else s.append(", "); 2141 k = keyAt(i); 2142 v = getAt(i++); 2143 s.append(k == this ? "(this collection)" : String.valueOf(k)) 2144 .append("=>") 2145 .append(v == this ? "(this collection)" : String.valueOf(v)); 2146 } 2147 s.append("}"); 2148 return s.toString(); 2149 } 2150 @Override 2151 public boolean equals(Object o) { 2152 if (o == this) 2153 return true; 2154 if (!(o instanceof Map)) 2155 return false; 2156 Map<?, ?> m = (Map<?, ?>) o; 2157 if (m.size() != size()) 2158 return false; 2159 return entrySet().containsAll(m.entrySet()); 2160 } 2161 2162 @GwtIncompatible 2163 private void writeObject(java.io.ObjectOutputStream s) 2164 throws java.io.IOException { 2165 final K[] key = this.key; 2166 final V[] value = this.value; 2167 final MapIterator i = new MapIterator(); 2168 s.defaultWriteObject(); 2169 for (int j = size, e; j-- != 0;) { 2170 e = i.nextEntry(); 2171 s.writeObject(key[e]); 2172 s.writeObject(value[e]); 2173 } 2174 } 2175 @GwtIncompatible 2176 @SuppressWarnings("unchecked") 2177 private void readObject(java.io.ObjectInputStream s) 2178 throws java.io.IOException, ClassNotFoundException { 2179 s.defaultReadObject(); 2180 n = arraySize(size, f); 2181 maxFill = maxFill(n, f); 2182 mask = n - 1; 2183 final K[] key = this.key = (K[]) new Object[n + 1]; 2184 final V[] value = this.value = (V[]) new Object[n + 1]; 2185 final IntVLA order = this.order = new IntVLA(n + 1); 2186 K k; 2187 V v; 2188 for (int i = size, pos; i-- != 0;) { 2189 k = (K) s.readObject(); 2190 v = (V) s.readObject(); 2191 if (k == null) { 2192 pos = n; 2193 containsNullKey = true; 2194 } else { 2195 pos = (hasher.hash(k)) 2196 & mask; 2197 while (!(key[pos] == null)) 2198 pos = (pos + 1) & mask; 2199 } 2200 2201 key[pos] = k; 2202 value[pos] = v; 2203 order.add(pos); 2204 } 2205 } 2206 2207 /** 2208 * Gets the value at the given index in the iteration order in constant time (random-access). 2209 * @param idx the index in the iteration order of the value to fetch 2210 * @return the value at the index, if the index is valid, otherwise the default return value 2211 */ 2212 public V getAt(final int idx) { 2213 int pos; 2214 if (idx < 0 || idx >= order.size) 2215 return defRetValue; 2216 // The starting point. 2217 if (key[pos = order.get(idx)] == null) 2218 return containsNullKey ? value[n] : defRetValue; 2219 return value[pos]; 2220 } 2221 /** 2222 * Gets the key at the given index in the iteration order in constant time (random-access). 2223 * @param idx the index in the iteration order of the key to fetch 2224 * @return the key at the index, if the index is valid, otherwise null 2225 */ 2226 public K keyAt(final int idx) { 2227 if (idx < 0 || idx >= order.size) 2228 return null; 2229 // The starting point. 2230 return key[order.get(idx)]; 2231 } 2232 2233 /** 2234 * Gets the key-value Map.Entry at the given index in the iteration order in constant time (random-access). 2235 * @param idx the index in the iteration order of the entry to fetch 2236 * @return the key-value entry at the index, if the index is valid, otherwise null 2237 */ 2238 public Entry<K, V> entryAt(final int idx) 2239 { 2240 if (idx < 0 || idx >= order.size) 2241 return null; 2242 return new MapEntry(order.get(idx)); 2243 } 2244 2245 /** 2246 * Removes the key and value at the given index in the iteration order in not-exactly constant time (though it still 2247 * should be efficient). 2248 * @param idx the index in the iteration order of the key and value to remove 2249 * @return the value removed, if there was anything removed, or the default return value otherwise (often null) 2250 */ 2251 public V removeAt(final int idx) { 2252 2253 if (idx < 0 || idx >= order.size) 2254 return defRetValue; 2255 int pos = order.get(idx); 2256 if (key[pos] == null) { 2257 if (containsNullKey) 2258 return removeNullEntry(); 2259 return defRetValue; 2260 } 2261 return removeEntry(pos); 2262 } 2263 /** 2264 * Gets a random value from this OrderedMap in constant time, using the given IRNG to generate a random number. 2265 * @param rng used to generate a random index for a value 2266 * @return a random value from this OrderedMap 2267 */ 2268 public V randomValue(IRNG rng) 2269 { 2270 return getAt(rng.nextInt(order.size)); 2271 } 2272 2273 /** 2274 * Gets a random key from this OrderedMap in constant time, using the given IRNG to generate a random number. 2275 * @param rng used to generate a random index for a key 2276 * @return a random key from this OrderedMap 2277 */ 2278 public K randomKey(IRNG rng) 2279 { 2280 return keyAt(rng.nextInt(order.size)); 2281 } 2282 2283 /** 2284 * Gets a random entry from this OrderedMap in constant time, using the given IRNG to generate a random number. 2285 * @param rng used to generate a random index for a entry 2286 * @return a random key-value entry from this OrderedMap 2287 */ 2288 public Entry<K, V> randomEntry(IRNG rng) 2289 { 2290 return new MapEntry(order.getRandomElement(rng)); 2291 } 2292 2293 /** 2294 * Randomly alters the iteration order for this OrderedMap using the given IRNG to shuffle. 2295 * @param rng used to generate a random ordering 2296 * @return this for chaining 2297 */ 2298 public OrderedMap<K, V> shuffle(IRNG rng) 2299 { 2300 if(size < 2) 2301 return this; 2302 order.shuffle(rng); 2303 return this; 2304 } 2305 2306 /** 2307 * Given an array or varargs of replacement indices for this OrderedMap's iteration order, reorders this so the 2308 * first item in the returned version is the same as {@code getAt(ordering[0])} (with some care taken for negative 2309 * or too-large indices), the second item in the returned version is the same as {@code getAt(ordering[1])}, etc. 2310 * <br> 2311 * Negative indices are considered reversed distances from the end of ordering, so -1 refers to the same index as 2312 * {@code ordering[ordering.length - 1]}. If ordering is smaller than {@code size()}, only the indices up to the 2313 * length of ordering will be modified. If ordering is larger than {@code size()}, only as many indices will be 2314 * affected as {@code size()}, and reversed distances are measured from the end of this Map's entries instead of 2315 * the end of ordering. Duplicate values in ordering will produce duplicate values in the returned Map. 2316 * <br> 2317 * This method modifies this OrderedMap in-place and also returns it for chaining. 2318 * @param ordering an array or varargs of int indices, where the nth item in ordering changes the nth item in this 2319 * Map to have the value currently in this Map at the index specified by the value in ordering 2320 * @return this for chaining, after modifying it in-place 2321 */ 2322 public OrderedMap<K, V> reorder(int... ordering) 2323 { 2324 order.reorder(ordering); 2325 return this; 2326 } 2327 private int alterEntry(final int pos) { 2328 int idx = fixOrder(pos); 2329 value[pos] = null; 2330 size--; 2331 shiftKeys(pos); 2332 return idx; 2333 } 2334 private int alterNullEntry() { 2335 int idx = fixOrder(n); 2336 containsNullKey = false; 2337 value[n] = null; 2338 size--; 2339 return idx; 2340 } 2341 /** 2342 * Swaps a key, original, for another key, replacement, while keeping replacement at the same point in the iteration 2343 * order as original and keeping it associated with the same value (which also keeps its iteration index). Unlike 2344 * the similar method {@link #alter(Object, Object)}, this will not change this OrderedMap if replacement is already 2345 * present. To contrast, alter() can reduce the size of the OrderedMap if both original and replacement are already 2346 * in the Map. If replacement is found, this returns the default return value, otherwise it switches out original 2347 * for replacement and returns whatever was associated with original. 2348 * @param original the key to find and swap out 2349 * @param replacement the key to replace original with 2350 * @return the value associated with original before, and replacement now 2351 */ 2352 public V alterCarefully(final K original, final K replacement) { 2353 if(!containsKey(replacement)) 2354 return alter(original, replacement); 2355 else 2356 return defRetValue; 2357 } 2358 /** 2359 * Swaps a key, original, for another key, replacement, while keeping replacement at the same point in the iteration 2360 * order as original and keeping it associated with the same value (which also keeps its iteration index). 2361 * Be aware that if both original and replacement are present in the OrderedMap, this will still replace original 2362 * with replacement but will also remove the other occurrence of replacement to avoid duplicate keys. This can throw 2363 * off the expected order because the duplicate could be at any point in the ordering when it is removed. You may 2364 * want to prefer {@link #alterCarefully(Object, Object)} if you don't feel like checking by hand for whether 2365 * replacement is already present, but using this method is perfectly reasonable if you know overlaps won't happen. 2366 * @param original the key to find and swap out 2367 * @param replacement the key to replace original with 2368 * @return the value associated with original before, and replacement now 2369 */ 2370 public V alter(final K original, final K replacement) { 2371 V v; 2372 int idx; 2373 if (original == null) { 2374 if (containsNullKey) { 2375 v = value[n]; 2376 idx = alterNullEntry(); 2377 putAt(replacement, v, idx); 2378 return v; 2379 } 2380 else 2381 v = defRetValue; 2382 return v; 2383 } 2384 K curr; 2385 final K[] key = this.key; 2386 int pos; 2387 // The starting point. 2388 if ((curr = key[pos = (hasher.hash(original)) & mask]) == null) 2389 return defRetValue; 2390 if (hasher.areEqual(original, curr)) 2391 { 2392 v = value[pos]; 2393 idx = alterEntry(pos); 2394 putAt(replacement, v, idx); 2395 return v; 2396 } 2397 while (true) { 2398 if ((curr = key[pos = (pos + 1) & mask]) == null) 2399 return defRetValue; 2400 if (hasher.areEqual(original, curr)) 2401 { 2402 v = value[pos]; 2403 idx = alterEntry(pos); 2404 putAt(replacement, v, idx); 2405 return v; 2406 } 2407 } 2408 } 2409 2410 public List<V> getMany(Collection<K> keys) 2411 { 2412 if(keys == null) 2413 return new ArrayList<>(1); 2414 ArrayList<V> vals = new ArrayList<>(keys.size()); 2415 for(K k : keys) 2416 { 2417 vals.add(get(k)); 2418 } 2419 return vals; 2420 } 2421 /** 2422 * Changes the K at the given index to replacement while keeping replacement at the same point in the ordering. 2423 * Be aware that if replacement is present in the OrderedMap, this will still replace the given index 2424 * with replacement but will also remove the other occurrence of replacement to avoid duplicate keys. This can throw 2425 * off the expected order because the duplicate could be at any point in the ordering when it is removed. You may 2426 * want to prefer {@link #alterAtCarefully(int, Object)} if you don't feel like checking by hand for whether 2427 * replacement is already present, but using this method is perfectly reasonable if you know overlaps won't happen. 2428 * @param index an index to replace the K key at 2429 * @param replacement another K key that will replace the original at the remembered index 2430 * @return the value associated with the possibly-altered key 2431 */ 2432 public V alterAt(int index, K replacement) 2433 { 2434 return alter(keyAt(index), replacement); 2435 } 2436 /** 2437 * Changes the K at the given index to replacement while keeping replacement at the same point in the ordering. 2438 * Unlike the similar method {@link #alterAt(int, Object)}, this will not change this OrderedMap if replacement is 2439 * already present. To contrast, alterAt() can reduce the size of the OrderedMap if replacement is already 2440 * in the Map. If replacement is found, this returns the default return value, otherwise it switches out the index 2441 * for replacement and returns whatever value was at the index before. 2442 * @param index an index to replace the K key at 2443 * @param replacement another K key that will replace the original at the remembered index 2444 * @return the value associated with the key at the altered index before, and replacement now 2445 */ 2446 public V alterAtCarefully(int index, K replacement) 2447 { 2448 return alterCarefully(keyAt(index), replacement); 2449 } 2450 2451 /** 2452 * If the specified key is not already associated with a value (or is mapped 2453 * to {@code null}) associates it with the given value and returns 2454 * {@code null}, else returns the current value. 2455 * 2456 * @param key key with which the specified value is to be associated 2457 * @param value value to be associated with the specified key 2458 * @return the previous value associated with the specified key, or 2459 * {@code null} if there was no mapping for the key. 2460 * (A {@code null} return can also indicate that the map 2461 * previously associated {@code null} with the key.) 2462 */ 2463 public V putIfAbsent(K key, V value) { 2464 V v = get(key); 2465 if(v == null) 2466 v = put(key, value); 2467 return v; 2468 } 2469 2470 /** 2471 * Removes the entry for the specified key only if it is currently 2472 * mapped to the specified value. 2473 * 2474 * @param key key with which the specified value is associated 2475 * @param value value expected to be associated with the specified key 2476 * @return {@code true} if the value was removed 2477 */ 2478 public boolean remove(Object key, Object value) { 2479 if (containsKey(key) && Objects.equals(get(key), value)) { 2480 remove(key); 2481 return true; 2482 } else 2483 return false; 2484 } 2485 2486 /** 2487 * Replaces the entry for the specified key only if currently 2488 * mapped to the specified value. The position in the iteration 2489 * order is retained. 2490 * 2491 * @param key key with which the specified value is associated 2492 * @param oldValue value expected to be associated with the specified key 2493 * @param newValue value to be associated with the specified key 2494 * @return {@code true} if the value was replaced 2495 */ 2496 public boolean replace(K key, V oldValue, V newValue) { 2497 if (containsKey(key)) { 2498 V v = get(key); 2499 if (v == oldValue || (oldValue != null && oldValue.equals(v))) { 2500 put(key, newValue); 2501 return true; 2502 } 2503 } 2504 return false; 2505 } 2506 2507 /** 2508 * Replaces the entry for the specified key only if it is 2509 * currently mapped to some value. Preserves the existing key's 2510 * position in the iteration order. 2511 * 2512 * @param key key with which the specified value is associated 2513 * @param value value to be associated with the specified key 2514 * @return the previous value associated with the specified key, or 2515 * {@code null} if there was no mapping for the key. 2516 * (A {@code null} return can also indicate that the map 2517 * previously associated {@code null} with the key.) 2518 */ 2519 public V replace(K key, V value) { 2520 if (containsKey(key)) { 2521 return put(key, value); 2522 } else 2523 return null; 2524 } 2525 /** 2526 * Given alternating key and value arguments in pairs, puts each key-value pair into this OrderedMap as if by 2527 * calling {@link #put(Object, Object)} repeatedly for each pair. This mimics the parameter syntax used for 2528 * {@link #makeMap(Object, Object, Object...)}, and can be used to retain that style of insertion after an 2529 * OrderedMap has been instantiated. 2530 * @param k0 the first key to add 2531 * @param v0 the first value to add 2532 * @param rest an array or vararg of keys and values in pairs; should contain alternating K, V, K, V... elements 2533 * @return this, after adding all viable key-value pairs given 2534 */ 2535 @SuppressWarnings("unchecked") 2536 public OrderedMap<K, V> putPairs(K k0, V v0, Object... rest) 2537 { 2538 if(rest == null || rest.length == 0) 2539 { 2540 put(k0, v0); 2541 return this; 2542 } 2543 put(k0, v0); 2544 2545 for (int i = 0; i < rest.length - 1; i+=2) { 2546 try { 2547 put((K) rest[i], (V) rest[i + 1]); 2548 }catch (ClassCastException ignored) { 2549 } 2550 } 2551 return this; 2552 } 2553 2554 /** 2555 * Makes an OrderedMap (OM) with the given load factor (which should be between 0.1 and 0.9), key and value types 2556 * inferred from the types of k0 and v0, and considers all remaining parameters key-value pairs, casting the Objects 2557 * at positions 0, 2, 4... etc. to K and the objects at positions 1, 3, 5... etc. to V. If rest has an odd-number 2558 * length, then it discards the last item. If any pair of items in rest cannot be cast to the correct type of K or 2559 * V, then this inserts nothing for that pair. This is similar to the makeOM method in the Maker class, but does not 2560 * allow setting the load factor (since that extra parameter can muddle how javac figures out which generic types 2561 * the map should use), nor does it log debug information if a cast fails. The result should be the same otherwise. 2562 * <br> 2563 * This is named makeMap to indicate that it expects key and value parameters, unlike a Set or List. This convention 2564 * may be extended to other data structures that also have static methods for instantiation. 2565 * @param k0 the first key; used to infer the types of other keys if generic parameters aren't specified. 2566 * @param v0 the first value; used to infer the types of other values if generic parameters aren't specified. 2567 * @param rest an array or vararg of keys and values in pairs; should contain alternating K, V, K, V... elements 2568 * @param <K> the type of keys in the returned OrderedMap; if not specified, will be inferred from k0 2569 * @param <V> the type of values in the returned OrderedMap; if not specified, will be inferred from v0 2570 * @return a freshly-made OrderedMap with K keys and V values, using k0, v0, and the contents of rest to fill it 2571 */ 2572 @SuppressWarnings("unchecked") 2573 public static <K, V> OrderedMap<K, V> makeMap(K k0, V v0, Object... rest) 2574 { 2575 if(rest == null || rest.length == 0) 2576 { 2577 OrderedMap<K, V> om = new OrderedMap<>(2); 2578 om.put(k0, v0); 2579 return om; 2580 } 2581 OrderedMap<K, V> om = new OrderedMap<>(1 + (rest.length >> 1)); 2582 om.put(k0, v0); 2583 2584 for (int i = 0; i < rest.length - 1; i+=2) { 2585 try { 2586 om.put((K) rest[i], (V) rest[i + 1]); 2587 }catch (ClassCastException ignored) { 2588 } 2589 } 2590 return om; 2591 } 2592 2593 /** 2594 * Makes an empty OrderedMap (OM); needs key and value types to be specified in order to work. For an empty 2595 * OrderedMap with String keys and Coord values, you could use {@code Maker.<String, Coord>makeOM()}. Using 2596 * the new keyword is probably just as easy in this case; this method is provided for completeness relative to 2597 * makeMap() with 2 or more parameters. 2598 * @param <K> the type of keys in the returned OrderedMap; cannot be inferred and must be specified 2599 * @param <V> the type of values in the returned OrderedMap; cannot be inferred and must be specified 2600 * @return an empty OrderedMap with the given key and value types. 2601 */ 2602 public static <K, V> OrderedMap<K, V> makeMap() 2603 { 2604 return new OrderedMap<>(); 2605 } 2606 2607 2608 /** 2609 * Sorts this whole OrderedMap on its keys using the supplied Comparator. 2610 * @param comparator a Comparator that can be used on the same type this uses for its keys (may need wildcards) 2611 */ 2612 public void sort(Comparator<? super K> comparator) 2613 { 2614 sort(comparator, 0, size); 2615 } 2616 2617 /** 2618 * Sorts a sub-range of this OrderedMap on its keys from what is currently the index {@code start} up to (but not 2619 * including) the index {@code end}, using the supplied Comparator. 2620 * @param comparator a Comparator that can be used on the same type this uses for its keys (may need wildcards) 2621 * @param start the first index of a key to sort (the index can change after this) 2622 * @param end the exclusive bound on the indices to sort; often this is just {@link #size()} 2623 */ 2624 public void sort(Comparator<? super K> comparator, int start, int end) 2625 { 2626 TimSort.sort(key, order, start, end, comparator); 2627 } 2628 /** 2629 * Sorts this whole OrderedMap on its values using the supplied Comparator. 2630 * @param comparator a Comparator that can be used on the same type this uses for its values (may need wildcards) 2631 */ 2632 public void sortByValue(Comparator<? super V> comparator) 2633 { 2634 sortByValue(comparator, 0, size); 2635 } 2636 2637 /** 2638 * Sorts a sub-range of this OrderedMap on its values from what is currently the index {@code start} up to (but not 2639 * including) the index {@code end}, using the supplied Comparator. 2640 * @param comparator a Comparator that can be used on the same type this uses for its values (may need wildcards) 2641 * @param start the first index of a value to sort (the index can change after this) 2642 * @param end the exclusive bound on the indices to sort; often this is just {@link #size()} 2643 */ 2644 public void sortByValue(Comparator<? super V> comparator, int start, int end) 2645 { 2646 TimSort.sort(value, order, start, end, comparator); 2647 } 2648 2649 /** 2650 * Reverses the iteration order in linear time. 2651 */ 2652 public void reverse() 2653 { 2654 order.reverse(); 2655 } 2656}