com.carrotsearch.hppcrt.HashContainers Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hppcrt Show documentation
Show all versions of hppcrt Show documentation
High Performance Primitive Collections Realtime
(fork of HPPC from Carrotsearch)
Fundamental data structures (maps, sets, lists, queues, heaps, sorts) generated for
combinations of object and primitive types to conserve JVM memory and speed
up execution. The Realtime fork intends to extend the existing collections, by tweaking to remove any dynamic allocations at runtime,
and to obtain low variance execution times whatever the input nature.
The newest version!
package com.carrotsearch.hppcrt;
public final class HashContainers
{
/**
* Maximum array size for hash containers (power-of-two and still
* allocable in Java, not a negative int).
*/
public final static int MAX_HASH_ARRAY_LENGTH = 0x80000000 >>> 1;
/**
* Minimum hash buffer size. (must be a power-of-two !)
*/
public final static int MIN_HASH_ARRAY_LENGTH = 1 << 3;
/**
* Default load factor.
*/
public final static float DEFAULT_LOAD_FACTOR = 0.75f;
/**
* Minimal sane load factor (90 empty slots per 100).
*/
public final static double MIN_LOAD_FACTOR = 10.0 / 100.0;
/**
* Maximum sane load factor (10 empty slot per 100).
*/
public final static double MAX_LOAD_FACTOR = 90.0 / 100.0;
/**
* No instances.
*/
private HashContainers() {
//nothing
}
/**
* Compute and return the maximum number of elements (inclusive) that can be
* stored in a hash container for a given load factor.
* @param loadFactor
*/
public static int maxElements(final double loadFactor) {
HashContainers.checkLoadFactor(loadFactor, HashContainers.MIN_LOAD_FACTOR, HashContainers.MAX_LOAD_FACTOR);
return HashContainers.expandAtCount(HashContainers.MAX_HASH_ARRAY_LENGTH, loadFactor) - 1;
}
/**
* Gives the minimum size if internal buffers able to accommodate elements,
* given loadFactor.
*
* @param elements
* @param loadFactor
*/
@SuppressWarnings("boxing")
public static int minBufferSize(final int elements, final double loadFactor) {
HashContainers.checkLoadFactor(loadFactor, HashContainers.MIN_LOAD_FACTOR, HashContainers.MAX_LOAD_FACTOR);
//Assure room for one additional slot (marking the not-allocated) + one more as safety margin.
long length = (long) (elements / loadFactor) + 2;
//Then, round it to the next power of 2.
length = Math.max(HashContainers.MIN_HASH_ARRAY_LENGTH, BitUtil.nextHighestPowerOfTwo(length));
if (length > HashContainers.MAX_HASH_ARRAY_LENGTH) {
throw new BufferAllocationException(
"Maximum array size exceeded for this load factor (elements: %d, load factor: %f)",
elements,
loadFactor);
}
return (int) length;
}
/**
* Gives the next (bigger) size authorized for a buffer
*
* @param arraySize
* @param elements
* @param loadFactor
*/
@SuppressWarnings("boxing")
public static int nextBufferSize(final int arraySize, final int elements, final double loadFactor) {
HashContainers.checkPowerOfTwo(arraySize);
if (arraySize == HashContainers.MAX_HASH_ARRAY_LENGTH) {
throw new BufferAllocationException(
"Maximum array size exceeded for this load factor (elements: %d, load factor: %f)",
elements,
loadFactor);
}
return arraySize << 1;
}
/**
* Compute the max number of elements
* that can be put into a hash container from a power of two arraySize,
* given a load factor loadFactor
* @param arraySize
* @param loadFactor
* @return
*/
public static int expandAtCount(final int arraySize, final double loadFactor) {
HashContainers.checkPowerOfTwo(arraySize);
// Take care of hash container invariant (there has to be at least one empty slot to ensure
// the lookup loop finds either the element or an empty slot).
return Math.min(arraySize - 1, (int) Math.ceil(arraySize * loadFactor));
}
/** */
@SuppressWarnings("boxing")
private static void checkLoadFactor(final double loadFactor, final double minAllowedInclusive,
final double maxAllowedInclusive) {
if (loadFactor < minAllowedInclusive || loadFactor > maxAllowedInclusive) {
throw new BufferAllocationException(
"The load factor should be in range [%.2f, %.2f]: %f",
minAllowedInclusive,
maxAllowedInclusive,
loadFactor);
}
}
/** */
private static void checkPowerOfTwo(final int arraySize) {
if (BitUtil.nextHighestPowerOfTwo(arraySize) != arraySize) {
throw new IllegalArgumentException("arraySize must be a power of two !");
}
}
}