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

com.carrotsearch.hppcrt.maps.LongFloatHashMap 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 long to float, 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. *

* *

Important note. The implementation uses power-of-two tables and linear * probing, which may cause poor performance (many collisions) if hash values are * not properly distributed. * * * * * */ @javax.annotation.Generated( date = "2016-01-30T23:09:35+0100", value = "KTypeVTypeHashMap.java") public class LongFloatHashMap implements LongFloatMap, Cloneable { protected float defaultValue = (0f); /** * 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 long [] keys; /** * Hash-indexed array holding all values associated to the keys. * stored in {@link #keys}. */ public float [] 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 float 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 LongFloatHashMap() { 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 LongFloatHashMap(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 LongFloatHashMap(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 LongFloatHashMap(final LongFloatAssociativeContainer container) { this(container.size()); putAll(container); } /** * {@inheritDoc} */ @Override public float put(long key, float value) { if (((key) == 0L)) { if (this.allocatedDefaultKey) { final float 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 long[] keys = ((this.keys)); int slot = (BitMixer.mix((key) , this.perturbation)) & mask; long existing; while (!((existing = keys[slot]) == 0L)) { if ( ((((key)) == ((existing))))) { final float 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 LongFloatAssociativeContainer container) { return putAll((Iterable) container); } /** * {@inheritDoc} */ @Override public int putAll(final Iterable iterable) { final int count = this.size(); for (final LongFloatCursor c : iterable) { put(c.key, c.value); } return this.size() - count; } /** * {@inheritDoc} */ @Override public boolean putIfAbsent(final long key, final float 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 float putOrAdd(final long key, float putValue, final float incrementValue) { if (containsKey(key)) { putValue = get(key); putValue = (float) (((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 float addTo(final long key, final float incrementValue) { return putOrAdd(key, incrementValue, incrementValue); } /** * Expand the internal storage buffers (capacity) and rehash. */ private void expandAndPut(final long pendingKey, final float pendingValue, final int freeSlot) { assert this.assigned == this.resizeAt; //default sentinel value is never in the keys[] array, so never trigger reallocs assert !((pendingKey) == 0L); // Try to allocate new buffers first. If we OOM, it'll be now without // leaving the data structure in an inconsistent state. final long[] oldKeys = ((this.keys)); final float[] 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; long key = (0L); float value = (0f); int slot = -1; final long[] keys = ((this.keys)); final float[] 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]) == 0L)) { value = oldValues[i]; slot = (BitMixer.mix((key) , (perturb))) & mask; //similar to put(), except all inserted keys are known to be unique. while ((!(((keys)[(slot)]) == 0L))) { 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 long[] keys = (new long[(capacity)]); final float[] values = (new float[(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 float remove(final long key) { if (((key) == 0L)) { if (this.allocatedDefaultKey) { final float previousValue = this.allocatedDefaultKeyValue; this.allocatedDefaultKey = false; return previousValue; } return this.defaultValue; } final int mask = this.keys.length - 1; final long[] keys = ((this.keys)); int slot = (BitMixer.mix((key) , this.perturbation)) & mask; long existing; while (!((existing = keys[slot]) == 0L) ) { if (((((key)) == ((existing))))) { final float 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 long[] keys = ((this.keys)); final float[] 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 long existing = keys[slot]; final float existingValue = values[slot]; if (((existing) == 0L)) { 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] = (0L); /* */ this.assigned--; } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public int removeAll(final LongContainer other) { final int before = this.size(); //1) other is a LongLookupContainer, 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 LongLookupContainer) { if (this.allocatedDefaultKey) { if (other.contains((0L))) { this.allocatedDefaultKey = false; } } final long[] keys = ((this.keys)); for (int i = 0; i < keys.length;) { long existing; if (!((existing = keys[i]) == 0L) && 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 LongCursor c : other) { remove(((c.value))); } } return before - this.size(); } /** * {@inheritDoc} */ @Override public int removeAll(final LongPredicate predicate) { final int before = this.size(); if (this.allocatedDefaultKey) { if (predicate.apply((0L))) { this.allocatedDefaultKey = false; } } final long[] keys = ((this.keys)); for (int i = 0; i < keys.length;) { long existing; if (!((existing = keys[i]) == 0L) && predicate.apply(existing)) { shiftConflictingKeys(i); // Shift, do not increment slot. } else { i++; } } return before - this.size(); } /** * {@inheritDoc} */ @Override public int removeAll(final LongFloatPredicate predicate) { final int before = this.size(); if (this.allocatedDefaultKey) { if (predicate.apply((0L), this.allocatedDefaultKeyValue)) { this.allocatedDefaultKey = false; } } final long[] keys = ((this.keys)); final float[] values = ((this.values)); for (int i = 0; i < keys.length;) { long existing; if (!((existing = keys[i]) == 0L) && predicate.apply(existing, values[i])) { shiftConflictingKeys(i); // Shift, do not increment slot. } else { i++; } } return before - this.size(); } /** * {@inheritDoc} */ @Override public float get(final long key) { if (((key) == 0L)) { if (this.allocatedDefaultKey) { return this.allocatedDefaultKeyValue; } return this.defaultValue; } final int mask = this.keys.length - 1; final long[] keys = ((this.keys)); int slot = (BitMixer.mix((key) , this.perturbation)) & mask; long existing; while (!((existing = keys[slot]) == 0L) ) { if (((((key)) == ((existing))))) { return ((this.values[slot])); } slot = (slot + 1) & mask; } //end while true return this.defaultValue; } /** * {@inheritDoc} */ @Override public boolean containsKey(final long key) { if (((key) == 0L)) { return this.allocatedDefaultKey; } final int mask = this.keys.length - 1; final long[] keys = ((this.keys)); int slot = (BitMixer.mix((key) , this.perturbation)) & mask; long existing; while (!((existing = keys[slot]) == 0L) ) { 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. LongArrays.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 long[] keys = ((this.keys)); final float[] values = ((this.values)); for (int i = keys.length; --i >= 0;) { long existing; if (!((existing = keys[i]) == 0L)) { 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; } /* */ LongFloatHashMap other = (LongFloatHashMap) obj; //must be of the same size if (other.size() != this.size()) { return false; } final EntryIterator it = this.iterator(); while (it.hasNext()) { final LongFloatCursor c = it.next(); if (!other.containsKey(c.key)) { //recycle it.release(); return false; } final float otherValue = other.get(c.key); if (!(Float.floatToIntBits((c.value)) == Float.floatToIntBits((otherValue)))) { //recycle it.release(); return false; } } //end while return true; } return false; } /** * An iterator implementation for {@link #iterator}. * Holds a LongFloatCursor returning * (key, value, index) = (long key, float value, index the position in keys {@link LongFloatHashMap#keys}, or keys.length for key = 0/null) */ public final class EntryIterator extends AbstractIterator { public final LongFloatCursor cursor; public EntryIterator() { this.cursor = new LongFloatCursor(); 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 LongFloatCursor fetch() { if (this.cursor.index == LongFloatHashMap.this.keys.length + 1) { if (LongFloatHashMap.this.allocatedDefaultKey) { this.cursor.index = LongFloatHashMap.this.keys.length; this.cursor.key = (0L); this.cursor.value = LongFloatHashMap.this.allocatedDefaultKeyValue; return this.cursor; } //no value associated with the default key, continue iteration... this.cursor.index = LongFloatHashMap.this.keys.length; } int i = this.cursor.index - 1; while (i >= 0 && !(!(((((LongFloatHashMap.this.keys)))[(i)]) == 0L))) { i--; } if (i == -1) { return done(); } this.cursor.index = i; this.cursor.key = ((LongFloatHashMap.this.keys[i])); this.cursor.value = ((LongFloatHashMap.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 = LongFloatHashMap.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((0L), this.allocatedDefaultKeyValue); } final long[] keys = ((this.keys)); final float[] 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--) { long existing; if (!((existing = keys[i]) == 0L)) { procedure.apply(existing, values[i]); } } return procedure; } /** * {@inheritDoc} */ @Override public T forEach(final T predicate) { if (this.allocatedDefaultKey) { if (!predicate.apply((0L), this.allocatedDefaultKeyValue)) { return predicate; } } final long[] keys = ((this.keys)); final float[] 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--) { long existing; if (!((existing = keys[i]) == 0L)) { 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 AbstractLongCollection implements LongLookupContainer { private final LongFloatHashMap owner = LongFloatHashMap.this; @Override public boolean contains(final long e) { return containsKey(e); } @Override public T forEach(final T procedure) { if (this.owner.allocatedDefaultKey) { procedure.apply((0L)); } final long[] 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--) { long existing; if (!((existing = keys[i]) == 0L)) { procedure.apply(existing); } } return procedure; } @Override public T forEach(final T predicate) { if (this.owner.allocatedDefaultKey) { if (!predicate.apply((0L))) { return predicate; } } final long[] 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--) { long existing; if (!((existing = keys[i]) == 0L)) { 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 LongPredicate predicate) { return this.owner.removeAll(predicate); } @Override public int removeAll(final long 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 = LongFloatHashMap.this.keys.length + 1; } @Override public void reset(final KeysIterator obj) { } }); @Override public long[] toArray(final long[] target) { int count = 0; if (this.owner.allocatedDefaultKey) { target[count++] = (0L); } final long[] keys = ((this.owner.keys)); for (int i = 0; i < keys.length; i++) { long existing; if (!((existing = keys[i]) == 0L)) { target[count++] = existing; } } assert count == this.owner.size(); return target; } }; /** * An iterator over the set of keys. * Holds a LongCursor returning (value, index) = (long key, index the position in buffer {@link LongFloatHashMap#keys}, or keys.length for key = 0/null.) */ public final class KeysIterator extends AbstractIterator { public final LongCursor cursor; public KeysIterator() { this.cursor = new LongCursor(); 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 LongCursor fetch() { if (this.cursor.index == LongFloatHashMap.this.keys.length + 1) { if (LongFloatHashMap.this.allocatedDefaultKey) { this.cursor.index = LongFloatHashMap.this.keys.length; this.cursor.value = (0L); return this.cursor; } //no value associated with the default key, continue iteration... this.cursor.index = LongFloatHashMap.this.keys.length; } int i = this.cursor.index - 1; while (i >= 0 && !(!(((((LongFloatHashMap.this.keys)))[(i)]) == 0L))) { i--; } if (i == -1) { return done(); } this.cursor.index = i; this.cursor.value = ((LongFloatHashMap.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 AbstractFloatCollection { private final LongFloatHashMap owner = LongFloatHashMap.this; /** * {@inheritDoc} */ @Override public int size() { return this.owner.size(); } /** * {@inheritDoc} */ @Override public int capacity() { return this.owner.capacity(); } @Override public boolean contains(final float value) { if (this.owner.allocatedDefaultKey && (Float.floatToIntBits((value)) == Float.floatToIntBits((this.owner.allocatedDefaultKeyValue)))) { return true; } // This is a linear scan over the values, but it's in the contract, so be it. final long[] keys = ((this.owner.keys)); final float[] values = ((this.owner.values)); for (int slot = 0; slot < keys.length; slot++) { if ((!(((keys)[(slot)]) == 0L)) && (Float.floatToIntBits((value)) == Float.floatToIntBits((values[slot])))) { return true; } } return false; } @Override public T forEach(final T procedure) { if (this.owner.allocatedDefaultKey) { procedure.apply(this.owner.allocatedDefaultKeyValue); } final long[] keys = ((this.owner.keys)); final float[] values = ((this.owner.values)); for (int slot = 0; slot < keys.length; slot++) { if ((!(((keys)[(slot)]) == 0L))) { 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 long[] keys = ((this.owner.keys)); final float[] values = ((this.owner.values)); for (int slot = 0; slot < keys.length; slot++) { if ((!(((keys)[(slot)]) == 0L))) { 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 float e) { final int before = this.owner.size(); if (this.owner.allocatedDefaultKey) { if ((Float.floatToIntBits((e)) == Float.floatToIntBits((this.owner.allocatedDefaultKeyValue)))) { this.owner.allocatedDefaultKey = false; } } final long[] keys = ((this.owner.keys)); final float[] values = ((this.owner.values)); for (int slot = 0; slot < keys.length;) { if ((!(((keys)[(slot)]) == 0L)) && (Float.floatToIntBits((e)) == Float.floatToIntBits((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 FloatPredicate predicate) { final int before = this.owner.size(); if (this.owner.allocatedDefaultKey) { if (predicate.apply(this.owner.allocatedDefaultKeyValue)) { this.owner.allocatedDefaultKey = false; } } final long[] keys = ((this.owner.keys)); final float[] values = ((this.owner.values)); for (int slot = 0; slot < keys.length;) { if ((!(((keys)[(slot)]) == 0L)) && 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 = LongFloatHashMap.this.keys.length + 1; } @Override public void reset(final ValuesIterator obj) { } }); @Override public float[] toArray(final float[] target) { int count = 0; if (this.owner.allocatedDefaultKey) { target[count++] = this.owner.allocatedDefaultKeyValue; } final long[] keys = ((this.owner.keys)); final float[] values = ((this.owner.values)); for (int i = 0; i < values.length; i++) { if ((!(((keys)[(i)]) == 0L))) { target[count++] = values[i]; } } assert count == this.owner.size(); return target; } } /** * An iterator over the set of values. * Holds a LongCursor returning (value, index) = (float value, index the position in buffer {@link LongFloatHashMap#values}, * or values.length for value = {@link LongFloatHashMap#allocatedDefaultKeyValue}). */ public final class ValuesIterator extends AbstractIterator { public final FloatCursor cursor; public ValuesIterator() { this.cursor = new FloatCursor(); 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 FloatCursor fetch() { if (this.cursor.index == LongFloatHashMap.this.values.length + 1) { if (LongFloatHashMap.this.allocatedDefaultKey) { this.cursor.index = LongFloatHashMap.this.values.length; this.cursor.value = LongFloatHashMap.this.allocatedDefaultKeyValue; return this.cursor; } //no value associated with the default key, continue iteration... this.cursor.index = LongFloatHashMap.this.keys.length; } int i = this.cursor.index - 1; while (i >= 0 && !(!(((((LongFloatHashMap.this.keys)))[(i)]) == 0L))) { i--; } if (i == -1) { return done(); } this.cursor.index = i; this.cursor.value = ((LongFloatHashMap.this.values[i])); return this.cursor; } } /** * {@inheritDoc} */ @Override public LongFloatHashMap clone() { //clone to size() to prevent some cases of exponential sizes, final LongFloatHashMap cloned = new LongFloatHashMap(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 LongFloatCursor 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 LongFloatHashMap from(final long[] keys, final float[] values) { if (keys.length != values.length) { throw new IllegalArgumentException("Arrays of keys and values must have an identical length."); } final LongFloatHashMap map = new LongFloatHashMap(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 LongFloatHashMap from( final LongFloatAssociativeContainer container) { return new LongFloatHashMap(container); } /** * Create a new hash map without providing the full generic signature * (constructor shortcut). */ public static LongFloatHashMap newInstance() { return new LongFloatHashMap(); } /** * Create a new hash map with initial capacity and load factor control. * (constructor shortcut). */ public static LongFloatHashMap newInstance(final int initialCapacity, final double loadFactor) { return new LongFloatHashMap(initialCapacity, loadFactor); } /** * Returns the "default value" value used in containers methods returning * "default value" */ @Override public float getDefaultValue() { return this.defaultValue; } /** * Set the "default value" value to be used in containers methods returning * "default value" */ @Override public void setDefaultValue(final float defaultValue) { this.defaultValue = defaultValue; } //Test for existence in template }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy