public class IntSet
extends java.lang.Object
implements java.io.Serializable
This class performs fast contains and remove (typically O(1), worst case O(n) but that is rare in practice). Add may be slightly slower, depending on hash collisions. Hashcodes are rehashed to reduce collisions and the need to resize. Load factors greater than 0.91 greatly increase the chances to resize to the next higher POT size.
Unordered sets and maps are not designed to provide especially fast iteration. Iteration is faster with OrderedSet, OrderedMap, and for primitive-valued keys, IntIntOrderedMap and IntDoubleOrderedMap.
This implementation uses linear probing with the backward shift algorithm for removal. Hashcodes are rehashed using Fibonacci
hashing, instead of the more common power-of-two mask, to better distribute poor hashCodes (see Malte
Skarupke's blog post). Linear probing continues to work even when all hashCodes collide, just more slowly.
This class is based on libGDX 1.9.11-SNAPSHOT's IntSet class, and fully replaces the older ShortSet class within
SquidLib's usage. Porting older code that uses ShortSet should be a little easier due to the addAll(short[])
and random(IRNG)
methods. ShortSet used the somewhat-problematic cuckoo-hashing technique, where this uses
the more standard linear probing (like OrderedSet
).
Modifier and Type | Class and Description |
---|---|
static class |
IntSet.IntSetIterator |
Modifier and Type | Field and Description |
---|---|
protected int |
mask
A bitmask used to confine hashcodes to the size of the table.
|
protected int |
shift
|
int |
size |
Constructor and Description |
---|
IntSet()
Creates a new set with an initial capacity of 51 and a load factor of 0.8.
|
IntSet(int initialCapacity)
Creates a new set with a load factor of 0.8.
|
IntSet(int initialCapacity,
float loadFactor)
Creates a new set with the specified initial capacity and load factor.
|
IntSet(IntSet set)
Creates a new set identical to the specified set.
|
Modifier and Type | Method and Description |
---|---|
boolean |
add(int key)
Returns true if the key was not already in the set.
|
void |
addAll(int... array) |
void |
addAll(int[] array,
int offset,
int length) |
void |
addAll(IntSet set) |
void |
addAll(IntVLA array) |
void |
addAll(IntVLA array,
int offset,
int length) |
void |
addAll(short[] array) |
void |
addAll(short[] array,
int offset,
int length) |
IntVLA |
appendInto(IntVLA array)
Appends to an existing (non-null)
IntVLA with all the int items in this IntSet. |
void |
clear() |
void |
clear(int maximumCapacity)
Clears the set and reduces the size of the backing arrays to be the specified capacity / loadFactor, if they are larger.
|
boolean |
contains(int key) |
void |
ensureCapacity(int additionalCapacity)
Increases the size of the backing array to accommodate the specified number of additional items / loadFactor.
|
boolean |
equals(java.lang.Object obj) |
int |
first() |
int |
hashCode() |
boolean |
isEmpty()
Returns true if the set is empty.
|
IntSet.IntSetIterator |
iterator()
Returns an iterator for the keys in the set.
|
boolean |
notEmpty()
Returns true if the set has one or more items.
|
protected int |
place(int item)
Returns an index between 0 (inclusive) and
mask (inclusive) for the specified item . |
int |
random(IRNG rng)
Gets a random int from this IntSet, using the given
IRNG to generate random values. |
boolean |
remove(int key)
Returns true if the key was removed.
|
void |
shrink(int maximumCapacity)
Reduces the size of the backing arrays to be the specified capacity / loadFactor, or less.
|
int[] |
toArray()
Allocates a new in array and fills it with the contents of this IntSet.
|
int[] |
toArray(int[] array)
Fills an existing (non-null) int array with as many items from this IntSet as will fit in the array, until either
the array is full or the IntSet has no more items to offer.
|
java.lang.String |
toString() |
static IntSet |
with(int... array) |
static IntSet |
with(IntVLA array) |
public int size
protected int shift
place(int)
to bit shift the upper bits of a long
into a usable range (>= 0 and <=
mask
). The shift can be negative, which is convenient to match the number of bits in mask: if mask is a 7-bit
number, a shift of -7 shifts the upper 7 bits into the lowest 7 positions. This class sets the shift > 32 and < 64,
which if used with an int will still move the upper bits of an int to the lower bits due to Java's implicit modulus on
shifts.
mask
can also be used to mask the low bits of a number, which may be faster for some hashcodes, if
place(int)
is overridden.
protected int mask
place(int)
is overriden, this can be used instead of shift
to isolate usable bits of a
hash.public IntSet()
public IntSet(int initialCapacity)
initialCapacity
- If not a power of two, it is increased to the next nearest power of two.public IntSet(int initialCapacity, float loadFactor)
initialCapacity
- If not a power of two, it is increased to the next nearest power of two.public IntSet(IntSet set)
protected int place(int item)
mask
(inclusive) for the specified item
.
The default implementation uses Fibonacci hashing on the item's Object.hashCode()
: the hashcode is multiplied by a
long constant (2 to the 64th, divided by the golden ratio) then the uppermost bits are shifted into the lowest positions to
obtain an index in the desired range. Multiplication by a long may be slower than int (eg on GWT) but greatly improves
rehashing, allowing even very poor hashcodes, such as those that only differ in their upper bits, to be used without high
collision rates. Fibonacci hashing has increased collision rates when all or most hashcodes are multiples of larger
Fibonacci numbers (see Malte
Skarupke's blog post).
This method can be overriden to customizing hashing. This may be useful eg in the unlikely event that most hashcodes are
Fibonacci numbers, if keys provide poor or incorrect hashcodes, or to simplify hashing if keys provide high quality
hashcodes and don't need Fibonacci hashing: return item.hashCode() & mask;
public boolean add(int key)
public void addAll(IntVLA array)
public void addAll(IntVLA array, int offset, int length)
public void addAll(int... array)
public void addAll(int[] array, int offset, int length)
public void addAll(short[] array)
public void addAll(short[] array, int offset, int length)
public void addAll(IntSet set)
public boolean remove(int key)
public boolean notEmpty()
public boolean isEmpty()
public void shrink(int maximumCapacity)
public void clear(int maximumCapacity)
public void clear()
public boolean contains(int key)
public int first()
public int random(IRNG rng)
IRNG
to generate random values.
If this IntSet is empty, throws an UnsupportedOperationException. This method operates in linear time, unlike
the random item retrieval methods in OrderedSet
and OrderedMap
, which take constant time.public void ensureCapacity(int additionalCapacity)
public int hashCode()
hashCode
in class java.lang.Object
public boolean equals(java.lang.Object obj)
equals
in class java.lang.Object
public java.lang.String toString()
toString
in class java.lang.Object
public IntSet.IntSetIterator iterator()
The same iterator instance is returned each time this method is called.
Use the IntSet.IntSetIterator
constructor for nested or multithreaded iteration.
public static IntSet with(int... array)
public int[] toArray()
public int[] toArray(int[] array)
array
- a non-null int array; can have a length that is the same as, more than or less than size
array
, after adding items from thisCopyright © Eben Howard 2012–2022. All rights reserved.