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