All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.carrotsearch.hppcrt.maps.IntShortHashMap Maven / Gradle / Ivy

package com.carrotsearch.hppcrt.maps;

import com.carrotsearch.hppcrt.*;
import com.carrotsearch.hppcrt.cursors.*;
import com.carrotsearch.hppcrt.predicates.*;
import com.carrotsearch.hppcrt.procedures.*;
import com.carrotsearch.hppcrt.hash.*;

  
  
  
// If RH is defined, RobinHood Hashing is in effect :
  

/**
 * A hash map of int to short, implemented using open
 * addressing with linear probing for collision resolution.
 *
 * 

* The internal buffers of this implementation ({@link #keys}, {@link #values}), * are always allocated to the nearest size that is a power of two. When * the capacity exceeds the given load factor, the buffer size is doubled. *

* * * * * * */ @javax.annotation.Generated( date = "2017-07-11T19:16:30+0200", value = "KTypeVTypeHashMap.java") public class IntShortHashMap implements IntShortMap, Cloneable { protected short defaultValue = ((short)0); /** * Hash-indexed array holding all keys. *

* Direct map iteration: iterate {keys[i], values[i]} for i in [0; keys.length[ where keys[i] != 0/null, then also * {0/null, {@link #allocatedDefaultKeyValue} } is in the map if {@link #allocatedDefaultKey} = true. *

*/ public int [] keys; /** * Hash-indexed array holding all values associated to the keys. * stored in {@link #keys}. */ public short [] values; /** * True if key = 0/null is in the map. */ public boolean allocatedDefaultKey = false; /** * if allocatedDefaultKey = true, contains the associated V to the key = 0/null */ public short allocatedDefaultKeyValue; /** * Cached number of assigned slots in {@link #keys}. */ protected int assigned; /** * The load factor for this map (fraction of allocated slots * before the buffers must be rehashed or reallocated). */ protected final double loadFactor; /** * Resize buffers when {@link #keys} hits this value. */ private int resizeAt; /** * Per-instance size perturbation * introduced in rehashing to create a unique key distribution. */ private final int perturbation = Containers.randomSeed32(); /** * Default constructor: Creates a hash map with the default capacity of {@link Containers#DEFAULT_EXPECTED_ELEMENTS}, * load factor of {@link HashContainers#DEFAULT_LOAD_FACTOR}. * *

See class notes about hash distribution importance.

*/ public IntShortHashMap() { this(Containers.DEFAULT_EXPECTED_ELEMENTS); } /** * Creates a hash map with the given initial capacity, default load factor of * {@link HashContainers#DEFAULT_LOAD_FACTOR}. * *

See class notes about hash distribution importance.

* * @param initialCapacity Initial capacity (greater than zero and automatically * rounded to the next power of two). */ public IntShortHashMap(final int initialCapacity) { this(initialCapacity, HashContainers.DEFAULT_LOAD_FACTOR); } /** * Creates a hash map with the given initial capacity, * load factor. * * @param loadFactor The load factor (greater than zero and smaller than 1). */ public IntShortHashMap(final int initialCapacity, final double loadFactor) { this.loadFactor = loadFactor; //take into account of the load factor to guarantee no reallocations before reaching initialCapacity. allocateBuffers(HashContainers.minBufferSize(initialCapacity, loadFactor)); } /** * Create a hash map from all key-value pairs of another container. */ public IntShortHashMap(final IntShortAssociativeContainer container) { this(container.size()); putAll(container); } /** * {@inheritDoc} */ @Override public short put(int key, short value) { if (((key) == 0)) { if (this.allocatedDefaultKey) { final short previousValue = this.allocatedDefaultKeyValue; this.allocatedDefaultKeyValue = value; return previousValue; } this.allocatedDefaultKeyValue = value; this.allocatedDefaultKey = true; return this.defaultValue; } final int mask = this.keys.length - 1; final int[] keys = ((this.keys)); int slot = (BitMixer.mix((key) , this.perturbation)) & mask; int existing; while (!((existing = keys[slot]) == 0)) { if ( ((((key)) == ((existing))))) { final short oldValue = ((this.values[slot])); this.values[slot] = value; return oldValue; } slot = (slot + 1) & mask; } //end while // Check if we need to grow. If so, reallocate new data, fill in the last element // and rehash. if (this.assigned == this.resizeAt) { expandAndPut(key, value, slot); } else { this.assigned++; keys[slot] = key; values[slot] = value; } return this.defaultValue; } /** * {@inheritDoc} */ @Override public int putAll(final IntShortAssociativeContainer container) { return putAll((Iterable) container); } /** * {@inheritDoc} */ @Override public int putAll(final Iterable iterable) { final int count = this.size(); for (final IntShortCursor c : iterable) { put(c.key, c.value); } return this.size() - count; } /** * {@inheritDoc} */ @Override public boolean putIfAbsent(final int key, final short value) { if (!containsKey(key)) { put(key, value); return true; } return false; } /** * If key exists, putValue is inserted into the map, * otherwise any existing value is incremented by additionValue. * * @param key * The key of the value to adjust. * @param putValue * The value to put if key does not exist. * @param incrementValue * The value to add to the existing value if key exists. * @return Returns the current value associated with key (after * changes). */ @SuppressWarnings("cast") @Override public short putOrAdd(final int key, short putValue, final short incrementValue) { if (containsKey(key)) { putValue = get(key); putValue = (short) (((putValue) + (incrementValue))); } put(key, putValue); return putValue; } /** * Adds incrementValue to any existing value for the given key * or inserts incrementValue if key did not previously exist. * * @param key The key of the value to adjust. * @param incrementValue The value to put or add to the existing value if key exists. * @return Returns the current value associated with key (after changes). */ @Override public short addTo(final int key, final short incrementValue) { return putOrAdd(key, incrementValue, incrementValue); } /** * Expand the internal storage buffers (capacity) and rehash. */ private void expandAndPut(final int pendingKey, final short pendingValue, final int freeSlot) { assert this.assigned == this.resizeAt; //default sentinel value is never in the keys[] array, so never trigger reallocs assert !((pendingKey) == 0); // Try to allocate new buffers first. If we OOM, it'll be now without // leaving the data structure in an inconsistent state. final int[] oldKeys = ((this.keys)); final short[] oldValues = ((this.values)); allocateBuffers(HashContainers.nextBufferSize(this.keys.length, this.assigned, this.loadFactor)); // We have succeeded at allocating new data so insert the pending key/value at // the free slot in the old arrays before rehashing. this.assigned++; oldKeys[freeSlot] = pendingKey; oldValues[freeSlot] = pendingValue; //for inserts final int mask = this.keys.length - 1; int key = (0); short value = ((short)0); int slot = -1; final int[] keys = ((this.keys)); final short[] values = ((this.values)); //iterate all the old arrays to add in the newly allocated buffers //It is important to iterate backwards to minimize the conflict chain length ! final int perturb = this.perturbation; for (int i = oldKeys.length; --i >= 0;) { //only consider non-empty slots, of course if (!((key = oldKeys[i]) == 0)) { value = oldValues[i]; slot = (BitMixer.mix((key) , (perturb))) & mask; //similar to put(), except all inserted keys are known to be unique. while ((!(((keys)[(slot)]) == 0))) { slot = (slot + 1) & mask; } //end while keys[slot] = key; values[slot] = value; } } } /** * Allocate internal buffers for a given capacity. * * @param capacity New capacity (must be a power of two). */ @SuppressWarnings("boxing") private void allocateBuffers(final int capacity) { try { final int[] keys = (new int[(capacity)]); final short[] values = (new short[(capacity)]); this.keys = keys; this.values = values; //allocate so that there is at least one slot that remains allocated = false //this is compulsory to guarantee proper stop in searching loops this.resizeAt = HashContainers.expandAtCount(capacity, this.loadFactor); } catch (final OutOfMemoryError e) { throw new BufferAllocationException( "Not enough memory to allocate buffers to grow from %d -> %d elements", e, (this.keys == null) ? 0 : this.keys.length, capacity); } } /** * {@inheritDoc} */ @Override public short remove(final int key) { if (((key) == 0)) { if (this.allocatedDefaultKey) { final short previousValue = this.allocatedDefaultKeyValue; this.allocatedDefaultKey = false; return previousValue; } return this.defaultValue; } final int mask = this.keys.length - 1; final int[] keys = ((this.keys)); int slot = (BitMixer.mix((key) , this.perturbation)) & mask; int existing; while (!((existing = keys[slot]) == 0) ) { if (((((key)) == ((existing))))) { final short value = ((this.values[slot])); shiftConflictingKeys(slot); return value; } slot = (slot + 1) & mask; } //end while true return this.defaultValue; } /** * Shift all the slot-conflicting keys allocated to (and including) slot. */ private void shiftConflictingKeys(int gapSlot) { final int mask = this.keys.length - 1; final int[] keys = ((this.keys)); final short[] values = ((this.values)); final int perturb = this.perturbation; // Perform shifts of conflicting keys to fill in the gap. int distance = 0; while (true) { final int slot = (gapSlot + (++distance)) & mask; final int existing = keys[slot]; final short existingValue = values[slot]; if (((existing) == 0)) { break; } final int idealSlotModMask = (BitMixer.mix((existing) , (perturb))) & mask; //original HPPC code: shift = (slot - idealSlot) & mask; //equivalent to shift = (slot & mask - idealSlot & mask) & mask; //since slot and idealSlotModMask are already folded, we have : final int shift = (slot - idealSlotModMask) & mask; if (shift >= distance) { // Entry at this position was originally at or before the gap slot. // Move the conflict-shifted entry to the gap's position and repeat the procedure // for any entries to the right of the current position, treating it // as the new gap. keys[gapSlot] = existing; values[gapSlot] = existingValue; gapSlot = slot; distance = 0; } } //end while // Mark the last found gap slot without a conflict as empty. keys[gapSlot] = (0); /* */ this.assigned--; } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public int removeAll(final IntContainer other) { final int before = this.size(); //1) other is a IntLookupContainer, so with fast lookup guarantees //and is bigger than this, so take advantage of both and iterate over this //and test other elements by their contains(). if (other.size() >= before && other instanceof IntLookupContainer) { if (this.allocatedDefaultKey) { if (other.contains((0))) { this.allocatedDefaultKey = false; } } final int[] keys = ((this.keys)); for (int i = 0; i < keys.length;) { int existing; if (!((existing = keys[i]) == 0) && other.contains(existing)) { shiftConflictingKeys(i); // Shift, do not increment slot. } else { i++; } } } else { //2) Do not use contains() from container, which may lead to O(n**2) execution times, //so it iterate linearly and call remove() from map which is O(1). for (final IntCursor c : other) { remove(((c.value))); } } return before - this.size(); } /** * {@inheritDoc} */ @Override public int removeAll(final IntPredicate predicate) { final int before = this.size(); if (this.allocatedDefaultKey) { if (predicate.apply((0))) { this.allocatedDefaultKey = false; } } final int[] keys = ((this.keys)); for (int i = 0; i < keys.length;) { int existing; if (!((existing = keys[i]) == 0) && predicate.apply(existing)) { shiftConflictingKeys(i); // Shift, do not increment slot. } else { i++; } } return before - this.size(); } /** * {@inheritDoc} */ @Override public int removeAll(final IntShortPredicate predicate) { final int before = this.size(); if (this.allocatedDefaultKey) { if (predicate.apply((0), this.allocatedDefaultKeyValue)) { this.allocatedDefaultKey = false; } } final int[] keys = ((this.keys)); final short[] values = ((this.values)); for (int i = 0; i < keys.length;) { int existing; if (!((existing = keys[i]) == 0) && predicate.apply(existing, values[i])) { shiftConflictingKeys(i); // Shift, do not increment slot. } else { i++; } } return before - this.size(); } /** * {@inheritDoc} */ @Override public short get(final int key) { if (((key) == 0)) { if (this.allocatedDefaultKey) { return this.allocatedDefaultKeyValue; } return this.defaultValue; } final int mask = this.keys.length - 1; final int[] keys = ((this.keys)); int slot = (BitMixer.mix((key) , this.perturbation)) & mask; int existing; while (!((existing = keys[slot]) == 0) ) { if (((((key)) == ((existing))))) { return ((this.values[slot])); } slot = (slot + 1) & mask; } //end while true return this.defaultValue; } /** * {@inheritDoc} */ @Override public boolean containsKey(final int key) { if (((key) == 0)) { return this.allocatedDefaultKey; } final int mask = this.keys.length - 1; final int[] keys = ((this.keys)); int slot = (BitMixer.mix((key) , this.perturbation)) & mask; int existing; while (!((existing = keys[slot]) == 0) ) { if (((((key)) == ((existing))))) { return true; } slot = (slot + 1) & mask; } //end while true return false; } /** * {@inheritDoc} */ @Override public void clear() { this.assigned = 0; // States are always cleared. this.allocatedDefaultKey = false; //Faster than Arrays.fill(keys, null); // Help the GC. IntArrays.blankArray(this.keys, 0, this.keys.length); } /** * {@inheritDoc} */ @Override public int size() { return this.assigned + (this.allocatedDefaultKey ? 1 : 0); } /** * {@inheritDoc} */ @Override public int capacity() { return this.resizeAt; } /** * {@inheritDoc} * *

Note that an empty container may still contain many deleted keys (that occupy buffer * space). Adding even a single element to such a container may cause rehashing.

*/ @Override public boolean isEmpty() { return size() == 0; } /** * {@inheritDoc} */ @Override public int hashCode() { int h = 0; if (this.allocatedDefaultKey) { h += BitMixer.mix(this.allocatedDefaultKeyValue); } final int[] keys = ((this.keys)); final short[] values = ((this.values)); for (int i = keys.length; --i >= 0;) { int existing; if (!((existing = keys[i]) == 0)) { h += BitMixer.mix(existing) ^ BitMixer.mix(values[i]); } } return h; } /** * {@inheritDoc} */ @Override public boolean equals(final Object obj) { if (obj != null) { if (obj == this) { return true; } //must be of the same class, subclasses are not comparable if (obj.getClass() != this.getClass()) { return false; } /* */ IntShortHashMap other = (IntShortHashMap) obj; //must be of the same size if (other.size() != this.size()) { return false; } final EntryIterator it = this.iterator(); while (it.hasNext()) { final IntShortCursor c = it.next(); if (!other.containsKey(c.key)) { //recycle it.release(); return false; } final short otherValue = other.get(c.key); if (!((c.value) == (otherValue))) { //recycle it.release(); return false; } } //end while return true; } return false; } /** * An iterator implementation for {@link #iterator}. * Holds a IntShortCursor returning * (key, value, index) = (int key, short value, index the position in keys {@link IntShortHashMap#keys}, or keys.length for key = 0/null) */ public final class EntryIterator extends AbstractIterator { public final IntShortCursor cursor; public EntryIterator() { this.cursor = new IntShortCursor(); this.cursor.index = -2; } /** * Iterate backwards w.r.t the buffer, to * minimize collision chains when filling another hash container (ex. with putAll()) */ @Override protected IntShortCursor fetch() { if (this.cursor.index == IntShortHashMap.this.keys.length + 1) { if (IntShortHashMap.this.allocatedDefaultKey) { this.cursor.index = IntShortHashMap.this.keys.length; this.cursor.key = (0); this.cursor.value = IntShortHashMap.this.allocatedDefaultKeyValue; return this.cursor; } //no value associated with the default key, continue iteration... this.cursor.index = IntShortHashMap.this.keys.length; } int i = this.cursor.index - 1; while (i >= 0 && !(!(((((IntShortHashMap.this.keys)))[(i)]) == 0))) { i--; } if (i == -1) { return done(); } this.cursor.index = i; this.cursor.key = ((IntShortHashMap.this.keys[i])); this.cursor.value = ((IntShortHashMap.this.values[i])); return this.cursor; } } /** * internal pool of EntryIterator */ protected final IteratorPool entryIteratorPool = new IteratorPool( new ObjectFactory() { @Override public EntryIterator create() { return new EntryIterator(); } @Override public void initialize(final EntryIterator obj) { obj.cursor.index = IntShortHashMap.this.keys.length + 1; } @Override public void reset(final EntryIterator obj) { } }); /** * {@inheritDoc} */ @Override public EntryIterator iterator() { //return new EntryIterator(); return this.entryIteratorPool.borrow(); } /** * {@inheritDoc} */ @Override public T forEach(final T procedure) { if (this.allocatedDefaultKey) { procedure.apply((0), this.allocatedDefaultKeyValue); } final int[] keys = ((this.keys)); final short[] values = ((this.values)); //Iterate in reverse for side-stepping the longest conflict chain //in another hash, in case apply() is actually used to fill another hash container. for (int i = keys.length - 1; i >= 0; i--) { int existing; if (!((existing = keys[i]) == 0)) { procedure.apply(existing, values[i]); } } return procedure; } /** * {@inheritDoc} */ @Override public T forEach(final T predicate) { if (this.allocatedDefaultKey) { if (!predicate.apply((0), this.allocatedDefaultKeyValue)) { return predicate; } } final int[] keys = ((this.keys)); final short[] values = ((this.values)); //Iterate in reverse for side-stepping the longest conflict chain //in another hash, in case apply() is actually used to fill another hash container. for (int i = keys.length - 1; i >= 0; i--) { int existing; if (!((existing = keys[i]) == 0)) { if (!predicate.apply(existing, values[i])) { break; } } } //end for return predicate; } /** * {@inheritDoc} * @return a new KeysCollection view of the keys of this map. */ @Override public KeysCollection keys() { return new KeysCollection(); } /** * A view of the keys inside this map. */ public final class KeysCollection extends AbstractIntCollection implements IntLookupContainer { private final IntShortHashMap owner = IntShortHashMap.this; @Override public boolean contains(final int e) { return containsKey(e); } @Override public T forEach(final T procedure) { if (this.owner.allocatedDefaultKey) { procedure.apply((0)); } final int[] keys = ((this.owner.keys)); //Iterate in reverse for side-stepping the longest conflict chain //in another hash, in case apply() is actually used to fill another hash container. for (int i = keys.length - 1; i >= 0; i--) { int existing; if (!((existing = keys[i]) == 0)) { procedure.apply(existing); } } return procedure; } @Override public T forEach(final T predicate) { if (this.owner.allocatedDefaultKey) { if (!predicate.apply((0))) { return predicate; } } final int[] keys = ((this.owner.keys)); //Iterate in reverse for side-stepping the longest conflict chain //in another hash, in case apply() is actually used to fill another hash container. for (int i = keys.length - 1; i >= 0; i--) { int existing; if (!((existing = keys[i]) == 0)) { if (!predicate.apply(existing)) { break; } } } return predicate; } /** * {@inheritDoc} */ @Override public KeysIterator iterator() { //return new KeysIterator(); return this.keyIteratorPool.borrow(); } /** * {@inheritDoc} */ @Override public int size() { return this.owner.size(); } /** * {@inheritDoc} */ @Override public int capacity() { return this.owner.capacity(); } @Override public void clear() { this.owner.clear(); } @Override public int removeAll(final IntPredicate predicate) { return this.owner.removeAll(predicate); } @Override public int removeAll(final int e) { final boolean hasKey = this.owner.containsKey(e); int result = 0; if (hasKey) { this.owner.remove(e); result = 1; } return result; } /** * internal pool of KeysIterator */ protected final IteratorPool keyIteratorPool = new IteratorPool( new ObjectFactory() { @Override public KeysIterator create() { return new KeysIterator(); } @Override public void initialize(final KeysIterator obj) { obj.cursor.index = IntShortHashMap.this.keys.length + 1; } @Override public void reset(final KeysIterator obj) { } }); @Override public int[] toArray(final int[] target) { int count = 0; if (this.owner.allocatedDefaultKey) { target[count++] = (0); } final int[] keys = ((this.owner.keys)); for (int i = 0; i < keys.length; i++) { int existing; if (!((existing = keys[i]) == 0)) { target[count++] = existing; } } assert count == this.owner.size(); return target; } }; /** * An iterator over the set of keys. * Holds a IntCursor returning (value, index) = (int key, index the position in buffer {@link IntShortHashMap#keys}, or keys.length for key = 0/null.) */ public final class KeysIterator extends AbstractIterator { public final IntCursor cursor; public KeysIterator() { this.cursor = new IntCursor(); this.cursor.index = -2; } /** * Iterate backwards w.r.t the buffer, to * minimize collision chains when filling another hash container (ex. with putAll()) */ @Override protected IntCursor fetch() { if (this.cursor.index == IntShortHashMap.this.keys.length + 1) { if (IntShortHashMap.this.allocatedDefaultKey) { this.cursor.index = IntShortHashMap.this.keys.length; this.cursor.value = (0); return this.cursor; } //no value associated with the default key, continue iteration... this.cursor.index = IntShortHashMap.this.keys.length; } int i = this.cursor.index - 1; while (i >= 0 && !(!(((((IntShortHashMap.this.keys)))[(i)]) == 0))) { i--; } if (i == -1) { return done(); } this.cursor.index = i; this.cursor.value = ((IntShortHashMap.this.keys[i])); return this.cursor; } } /** * {@inheritDoc} * @return a new ValuesCollection view of the values of this map. */ @Override public ValuesCollection values() { return new ValuesCollection(); } /** * A view over the set of values of this map. */ public final class ValuesCollection extends AbstractShortCollection { private final IntShortHashMap owner = IntShortHashMap.this; /** * {@inheritDoc} */ @Override public int size() { return this.owner.size(); } /** * {@inheritDoc} */ @Override public int capacity() { return this.owner.capacity(); } @Override public boolean contains(final short value) { if (this.owner.allocatedDefaultKey && ((value) == (this.owner.allocatedDefaultKeyValue))) { return true; } // This is a linear scan over the values, but it's in the contract, so be it. final int[] keys = ((this.owner.keys)); final short[] values = ((this.owner.values)); for (int slot = 0; slot < keys.length; slot++) { if ((!(((keys)[(slot)]) == 0)) && ((value) == (values[slot]))) { return true; } } return false; } @Override public T forEach(final T procedure) { if (this.owner.allocatedDefaultKey) { procedure.apply(this.owner.allocatedDefaultKeyValue); } final int[] keys = ((this.owner.keys)); final short[] values = ((this.owner.values)); for (int slot = 0; slot < keys.length; slot++) { if ((!(((keys)[(slot)]) == 0))) { procedure.apply(values[slot]); } } return procedure; } @Override public T forEach(final T predicate) { if (this.owner.allocatedDefaultKey) { if (!predicate.apply(this.owner.allocatedDefaultKeyValue)) { return predicate; } } final int[] keys = ((this.owner.keys)); final short[] values = ((this.owner.values)); for (int slot = 0; slot < keys.length; slot++) { if ((!(((keys)[(slot)]) == 0))) { if (!predicate.apply(values[slot])) { break; } } } return predicate; } @Override public ValuesIterator iterator() { // return new ValuesIterator(); return this.valuesIteratorPool.borrow(); } /** * {@inheritDoc} * Indeed removes all the (key,value) pairs matching * (key ? , e) with the same e, from the map. */ @Override public int removeAll(final short e) { final int before = this.owner.size(); if (this.owner.allocatedDefaultKey) { if (((e) == (this.owner.allocatedDefaultKeyValue))) { this.owner.allocatedDefaultKey = false; } } final int[] keys = ((this.owner.keys)); final short[] values = ((this.owner.values)); for (int slot = 0; slot < keys.length;) { if ((!(((keys)[(slot)]) == 0)) && ((e) == (values[slot]))) { shiftConflictingKeys(slot); // Shift, do not increment slot. } else { slot++; } } return before - this.owner.size(); } /** * {@inheritDoc} * Indeed removes all the (key,value) pairs matching * the predicate for the values, from the map. */ @Override public int removeAll(final ShortPredicate predicate) { final int before = this.owner.size(); if (this.owner.allocatedDefaultKey) { if (predicate.apply(this.owner.allocatedDefaultKeyValue)) { this.owner.allocatedDefaultKey = false; } } final int[] keys = ((this.owner.keys)); final short[] values = ((this.owner.values)); for (int slot = 0; slot < keys.length;) { if ((!(((keys)[(slot)]) == 0)) && predicate.apply(values[slot])) { shiftConflictingKeys(slot); // Shift, do not increment slot. } else { slot++; } } return before - this.owner.size(); } /** * {@inheritDoc} * Alias for clear() the whole map. */ @Override public void clear() { this.owner.clear(); } /** * internal pool of ValuesIterator */ protected final IteratorPool valuesIteratorPool = new IteratorPool( new ObjectFactory() { @Override public ValuesIterator create() { return new ValuesIterator(); } @Override public void initialize(final ValuesIterator obj) { obj.cursor.index = IntShortHashMap.this.keys.length + 1; } @Override public void reset(final ValuesIterator obj) { } }); @Override public short[] toArray(final short[] target) { int count = 0; if (this.owner.allocatedDefaultKey) { target[count++] = this.owner.allocatedDefaultKeyValue; } final int[] keys = ((this.owner.keys)); final short[] values = ((this.owner.values)); for (int i = 0; i < values.length; i++) { if ((!(((keys)[(i)]) == 0))) { target[count++] = values[i]; } } assert count == this.owner.size(); return target; } } /** * An iterator over the set of values. * Holds a IntCursor returning (value, index) = (short value, index the position in buffer {@link IntShortHashMap#values}, * or values.length for value = {@link IntShortHashMap#allocatedDefaultKeyValue}). */ public final class ValuesIterator extends AbstractIterator { public final ShortCursor cursor; public ValuesIterator() { this.cursor = new ShortCursor(); this.cursor.index = -2; } /** * Iterate backwards w.r.t the buffer, to * minimize collision chains when filling another hash container (ex. with putAll()) */ @Override protected ShortCursor fetch() { if (this.cursor.index == IntShortHashMap.this.values.length + 1) { if (IntShortHashMap.this.allocatedDefaultKey) { this.cursor.index = IntShortHashMap.this.values.length; this.cursor.value = IntShortHashMap.this.allocatedDefaultKeyValue; return this.cursor; } //no value associated with the default key, continue iteration... this.cursor.index = IntShortHashMap.this.keys.length; } int i = this.cursor.index - 1; while (i >= 0 && !(!(((((IntShortHashMap.this.keys)))[(i)]) == 0))) { i--; } if (i == -1) { return done(); } this.cursor.index = i; this.cursor.value = ((IntShortHashMap.this.values[i])); return this.cursor; } } /** * {@inheritDoc} */ @Override public IntShortHashMap clone() { //clone to size() to prevent some cases of exponential sizes, final IntShortHashMap cloned = new IntShortHashMap(this.size(), this.loadFactor); //We must NOT clone because of independent perturbations seeds cloned.putAll(this); return cloned; } /** * Convert the contents of this map to a human-friendly string. */ @Override public String toString() { final StringBuilder buffer = new StringBuilder(); buffer.append("["); boolean first = true; for (final IntShortCursor cursor : this) { if (!first) { buffer.append(", "); } buffer.append(cursor.key); buffer.append("=>"); buffer.append(cursor.value); first = false; } buffer.append("]"); return buffer.toString(); } /** * Creates a hash map from two index-aligned arrays of key-value pairs. Default load factor is used. */ public static IntShortHashMap from(final int[] keys, final short[] values) { if (keys.length != values.length) { throw new IllegalArgumentException("Arrays of keys and values must have an identical length."); } final IntShortHashMap map = new IntShortHashMap(keys.length); for (int i = 0; i < keys.length; i++) { map.put(keys[i], values[i]); } return map; } /** * Create a hash map from another associative container. (constructor shortcut) Default load factor is used. */ public static IntShortHashMap from( final IntShortAssociativeContainer container) { return new IntShortHashMap(container); } /** * Create a new hash map without providing the full generic signature * (constructor shortcut). */ public static IntShortHashMap newInstance() { return new IntShortHashMap(); } /** * Create a new hash map with initial capacity and load factor control. * (constructor shortcut). */ public static IntShortHashMap newInstance(final int initialCapacity, final double loadFactor) { return new IntShortHashMap(initialCapacity, loadFactor); } /** * Returns the "default value" value used in containers methods returning * "default value" */ @Override public short getDefaultValue() { return this.defaultValue; } /** * Set the "default value" value to be used in containers methods returning * "default value" */ @Override public void setDefaultValue(final short defaultValue) { this.defaultValue = defaultValue; } //Test for existence in template }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy