Class MultiArrangement<K>
- All Implemented Interfaces:
Serializable
,Cloneable
,Iterable<K>
public class MultiArrangement<K> extends Object implements Iterable<K>, Serializable, Cloneable
Arrangement
, but is bag-like instead of set-like, allowing repeats of the same
key with different positions in the ordering. Useful for various indirection techniques where you want to be able to
retrieve a value in several ways, such as with multiple MultiArrangements all sharing the same ordering but with
different types for keys.
Originally, this started as a generic linked hash map with with a fast implementation, originally from fastutil as Object2IntLinkedOpenHashMap but modified to support indexed access. The code is extremely close to
OrderedMap
,
and like OrderedMap you can look up keys by index, but this is specialized to int values which it can automatically assign.
Instances of this class use a hash table to represent a map. The table is filled up to a specified load factor, and then doubled in size to accommodate new entries. If the table is emptied below one fourth 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 process.
Note that clear()
does not modify the hash table size. Rather, a family of trimming methods lets you control the size of the table; this is particularly useful if
you reuse instances of this class.
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
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, IntVLA
, and is modifiable with this
class' reorder(int...)
and shuffle(IRNG)
methods, among other tools.
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 firstKey()
without
having to create an iterator; however, this class partially violates the SortedMap
contract because all submap methods throw an exception and comparator()
returns always
null
.
Additional methods, such as getAndMoveToFirst()
, make it easy to use instances of this class as a cache (e.g., with LRU policy).
Thank you, Sebastiano Vigna, for making FastUtil available to the public with such high quality.
See https://github.com/vigna/fastutil for the original library.
- Author:
- Sebastiano Vigna (responsible for all the hard parts), Tommy Ettinger (mostly responsible for squashing several layers of parent classes into one monster class)
- See Also:
- Serialized Form
-
Nested Class Summary
Nested Classes Modifier and Type Class Description class
MultiArrangement.KeyIterator
An iterator on keys.class
MultiArrangement.KeyList
class
MultiArrangement.ValueCollection
class
MultiArrangement.ValueIterator
An iterator on values. -
Field Summary
Fields Modifier and Type Field Description protected boolean
containsNullKey
Whether this set contains the key zero.static int
DEFAULT_INITIAL_SIZE
The initial default size of a hash table.static float
DEFAULT_LOAD_FACTOR
The default load factor of a hash table.protected int
defRetValue
Default return value.float
f
The acceptable load factor.static float
FAST_LOAD_FACTOR
The load factor for a (usually small) table that is meant to be particularly fast.protected int
first
The index of the first entry in iteration order.protected CrossHash.IHasher
hasher
protected K[]
key
The array of keys.protected MultiArrangement.KeyList
keys
Cached set of keys.protected int
last
The index of the last entry in iteration order.protected int
mask
The mask for wrapping a position counter.protected int
maxFill
Threshold after which we rehash.protected int
n
The current table size.protected IntVLA
order
protected int
size
Number of entries in the set (including the key zero, if present).protected IntVLA[]
value
The array of values.protected IntVLA
values
Cached collection of values.static float
VERY_FAST_LOAD_FACTOR
The load factor for a (usually very small) table that is meant to be extremely fast. -
Constructor Summary
Constructors Constructor Description MultiArrangement()
Creates a new MultiArrangement with initial expected 16 entries and 0.5f as load factor.MultiArrangement(int expected)
Creates a new MultiArrangement with 0.5f as load factor.MultiArrangement(int expected, float f)
Creates a new MultiArrangement.MultiArrangement(int expected, float f, CrossHash.IHasher hasher)
Creates a new Arrangement.MultiArrangement(int expected, CrossHash.IHasher hasher)
Creates a new Arrangement with 0.5f as load factor.MultiArrangement(Collection<K> keyColl)
Creates a new Arrangement using the elements of an array.MultiArrangement(Collection<K> keyColl, float f)
Creates a new Arrangement using the given collection of keys.MultiArrangement(K[] keyArray)
Creates a new Arrangement with 0.5f as load factor using the elements of an array.MultiArrangement(K[] keyArray, float f)
Creates a new MultiArrangement using the elements of an array.MultiArrangement(K[] keyArray, float f, CrossHash.IHasher hasher)
Creates a new Arrangement using the elements of two parallel arrays.MultiArrangement(K[] keyArray, CrossHash.IHasher hasher)
Creates a new Arrangement with 0.5f as load factor using the elements of two parallel arrays.MultiArrangement(CrossHash.IHasher hasher)
Creates a new Arrangement with initial expected 16 entries and 0.5f as load factor.MultiArrangement(MultiArrangement<? extends K> a)
-
Method Summary
Modifier and Type Method Description int
add(K k)
void
addAll(Collection<? extends K> keyArray)
void
addAll(K[] keyArray)
void
addAllIfAbsent(Collection<? extends K> keyArray)
void
addAllIfAbsent(Map<? extends K,? extends Integer> m)
void
addAllIfAbsent(K[] keyArray)
int
addAt(int idx, K k)
Equivalent toadd(Object)
, except that it can place k at any point in the ordering (shifting up later entries and changing their values to match their new positions in the ordering).int
addIfAbsent(K k)
boolean
alter(K original, K replacement)
Swaps a key, original, for another key, replacement, while keeping replacement at the same point in the iteration order as original and keeping it associated with the same value (which also keeps its iteration index).int
append(IntVLA container, Object k)
Different from the typical get method; adds to the non-null IntVLA, container, filling with any positions associated with k in this MultiArrangement.static int
arraySize(int expected, float f)
Returns the least power of two smaller than or equal to 230 and larger than or equal toMath.ceil( expected / f )
.void
clear()
MultiArrangement<K>
clone()
Returns a deep copy of this map.Comparator<? super K>
comparator()
boolean
containsKey(Object k)
boolean
containsValue(int v)
boolean
containsValue(Object ov)
boolean
equals(Object o)
K
firstKey()
Returns the first key of this map in iteration order.protected void
fixOrder(int i)
protected void
fixOrder(int s, int d)
Modifies the link vector for a shift from s to d.protected void
fixValues()
int
get(IntVLA container, Object k)
Different from the typical get method; clears the non-null IntVLA, container, and fills it with any positions associated with k in this MultiArrangement.int[]
getArray(Collection<? extends K> keys)
int[]
getArray(K[] keys)
int
getAt(int idx)
Gets the value at the given index in the iteration order in constant time (random-access).IntVLA
getMany(Iterable<? extends K> keys)
int
hashCode()
Returns a hash code for this map.SortedMap<K,Integer>
headMap(K to)
boolean
isEmpty()
Iterator<K>
iterator()
Returns an iterator over elements of typeT
.K
keyAt(int idx)
Gets the key at the given index in the iteration order in constant time (random-access).MultiArrangement.KeyList
keyList()
ArrayList<K>
keysAsArrayList()
OrderedSet<K>
keysAt(int... positions)
OrderedSet<K>
keysAt(IntVLA positions)
K
lastKey()
Returns the last key of this map in iteration order.static int
maxFill(int n, float f)
Returns the maximum number of entries that can be filled before rehashing.static long
maxFill(long n, float f)
Returns the maximum number of entries that can be filled before rehashing.protected int
positionOf(Object k)
K
randomKey(IRNG rng)
Gets a random key from this MultiArrangement in constant time, using the given IRNG to generate a random number.protected void
rehash(int newN)
Rehashes the map.protected int
rem(Object k)
int
remove(Object o)
K
removeAt(int idx)
Removes the key and value at the given index in the iteration order in not-exactly constant time (though it still should be efficient).K
removeFirst()
Removes the mapping associated with the first key in iteration order.int
removeInt(Object k)
K
removeLast()
Removes the mapping associated with the last key in iteration order.MultiArrangement<K>
reorder(int... ordering)
Given an array or varargs of replacement indices for this MultiArrangement's iteration order, reorders this so the first item in the returned version is the same asgetAt(ordering[0])
(with some care taken for negative or too-large indices), the second item in the returned version is the same asgetAt(ordering[1])
, etc.boolean
retainAll(Collection<?> c)
Retains in this collection only elements from the given collection.protected void
shiftKeys(int pos)
Shifts left entries with the specified hash code, starting at the specified position, and empties the resulting free entry.protected void
shiftKeysValues(int pos)
Shifts left entries with the specified hash code, starting at the specified position, and empties the resulting free entry.MultiArrangement<K>
shuffle(IRNG rng)
Randomly alters the iteration order for this MultiArrangement using the given IRNG to shuffle.int
size()
SortedMap<K,Integer>
subMap(K from, K to)
boolean
swap(K left, K right)
Swaps the positions in the ordering for the given items, if they are both present.boolean
swapIndices(int left, int right)
Swaps the given indices in the ordering, if they are both ints between 0 and size.SortedMap<K,Integer>
tailMap(K from)
MultiArrangement<K>
take(int amount)
Produces a copy of this MultiArrangement, but only using up to the given amount of items to take.String
toString()
boolean
trim()
Rehashes the map, making the table as small as possible.boolean
trim(int n)
Rehashes this map if the table is too large.ArrayList<Integer>
values()
int[]
valuesAsArray()
IntVLA
valuesAsIntVLA()
ArrayList<Integer>
valuesAsList()
-
Field Details
-
key
The array of keys. -
value
The array of values. -
mask
The mask for wrapping a position counter. -
containsNullKey
Whether this set contains the key zero. -
first
The index of the first entry in iteration order. It is valid iffsize
is nonzero; otherwise, it contains -1. -
last
The index of the last entry in iteration order. It is valid iffsize
is nonzero; otherwise, it contains -1. -
order
-
n
The current table size. -
maxFill
Threshold after which we rehash. It must be the table size timesf
. -
size
Number of entries in the set (including the key zero, if present). -
f
The acceptable load factor. -
keys
Cached set of keys. -
values
Cached collection of values. -
defRetValue
Default return value.- See Also:
- Constant Field Values
-
DEFAULT_INITIAL_SIZE
The initial default size of a hash table.- See Also:
- Constant Field Values
-
DEFAULT_LOAD_FACTOR
The default load factor of a hash table.- See Also:
- Constant Field Values
-
FAST_LOAD_FACTOR
The load factor for a (usually small) table that is meant to be particularly fast.- See Also:
- Constant Field Values
-
VERY_FAST_LOAD_FACTOR
The load factor for a (usually very small) table that is meant to be extremely fast.- See Also:
- Constant Field Values
-
hasher
-
-
Constructor Details
-
MultiArrangement
Creates a new MultiArrangement.The actual table size will be the least power of two greater than
expected
/f
.- Parameters:
expected
- the expected number of elements in the hash set.f
- the load factor.
-
MultiArrangement
Creates a new MultiArrangement with 0.5f as load factor.- Parameters:
expected
- the expected number of elements in the MultiArrangement.
-
MultiArrangement
public MultiArrangement()Creates a new MultiArrangement with initial expected 16 entries and 0.5f as load factor. -
MultiArrangement
-
MultiArrangement
Creates a new MultiArrangement using the elements of an array.- Parameters:
keyArray
- the array of keys of the new MultiArrangement.f
- the load factor.- Throws:
IllegalArgumentException
- ifk
andv
have different lengths.
-
MultiArrangement
Creates a new Arrangement using the elements of an array.- Parameters:
keyColl
- the collection of keys of the new Arrangement.- Throws:
IllegalArgumentException
- ifk
andv
have different lengths.
-
MultiArrangement
Creates a new Arrangement using the given collection of keys.- Parameters:
keyColl
- the collection of keys of the new Arrangement.f
- the load factor.- Throws:
IllegalArgumentException
- ifk
andv
have different lengths.
-
MultiArrangement
Creates a new Arrangement with 0.5f as load factor using the elements of an array.- Parameters:
keyArray
- the array of keys of the new Arrangement.- Throws:
IllegalArgumentException
- ifk
andv
have different lengths.
-
MultiArrangement
Creates a new Arrangement.The actual table size will be the least power of two greater than
expected
/f
.- Parameters:
expected
- the expected number of elements in the hash set.f
- the load factor.hasher
- used to hash items; typically only needed when K is an array, where CrossHash has implementations
-
MultiArrangement
Creates a new Arrangement with 0.5f as load factor.- Parameters:
expected
- the expected number of elements in the Arrangement.hasher
- used to hash items; typically only needed when K is an array, where CrossHash has implementations
-
MultiArrangement
Creates a new Arrangement with initial expected 16 entries and 0.5f as load factor. -
MultiArrangement
Creates a new Arrangement using the elements of two parallel arrays.- Parameters:
keyArray
- the array of keys of the new Arrangement.f
- the load factor.hasher
- used to hash items; typically only needed when K is an array, where CrossHash has implementations- Throws:
IllegalArgumentException
- ifk
andv
have different lengths.
-
MultiArrangement
Creates a new Arrangement with 0.5f as load factor using the elements of two parallel arrays.- Parameters:
keyArray
- the array of keys of the new Arrangement.hasher
- used to hash items; typically only needed when K is an array, where CrossHash has implementations- Throws:
IllegalArgumentException
- ifk
andv
have different lengths.
-
-
Method Details
-
addAll
-
addAll
-
addAllIfAbsent
-
addAllIfAbsent
-
addAllIfAbsent
-
add
-
addIfAbsent
-
fixValues
-
shiftKeys
Shifts left entries with the specified hash code, starting at the specified position, and empties the resulting free entry.- Parameters:
pos
- a starting position.
-
shiftKeysValues
Shifts left entries with the specified hash code, starting at the specified position, and empties the resulting free entry.- Parameters:
pos
- a starting position.
-
rem
-
remove
-
removeInt
-
removeFirst
Removes the mapping associated with the first key in iteration order.- Returns:
- the value previously associated with the first key in iteration order.
- Throws:
NoSuchElementException
- is this map is empty.
-
removeLast
Removes the mapping associated with the last key in iteration order.- Returns:
- the value previously associated with the last key in iteration order.
- Throws:
NoSuchElementException
- is this map is empty.
-
get
Different from the typical get method; clears the non-null IntVLA, container, and fills it with any positions associated with k in this MultiArrangement. If you want to append to container instead of clearing it, useappend(IntVLA, Object)
.- Parameters:
container
- a non-null IntVLA; will be modified! Even if no entries are added, will be clearedk
- a K object or something that can be treated as one to search for- Returns:
- the number of items added to container; 0 if none were added
-
append
Different from the typical get method; adds to the non-null IntVLA, container, filling with any positions associated with k in this MultiArrangement. If you want a more convenient method for the case where you want container to hold only the items associated with k (discarding old contents), useget(IntVLA, Object)
.- Parameters:
container
- a non-null IntVLA; will be modified unless nothing is associated with kk
- a K object or something that can be treated as one to search for- Returns:
- the number of items added to container; 0 if none were added
-
containsKey
-
containsValue
-
containsValue
-
clear
-
size
-
isEmpty
-
iterator
Returns an iterator over elements of typeT
. -
fixOrder
-
fixOrder
Modifies the link vector for a shift from s to d.
This method will complete in logarithmic time or better.- Parameters:
s
- the source position.d
- the destination position.
-
firstKey
Returns the first key of this map in iteration order.- Returns:
- the first key in iteration order.
-
lastKey
Returns the last key of this map in iteration order.- Returns:
- the last key in iteration order.
-
retainAll
Retains in this collection only elements from the given collection.- Parameters:
c
- a collection.- Returns:
true
if this collection changed as a result of the call.
-
comparator
-
tailMap
-
headMap
-
subMap
-
keyList
-
keysAsArrayList
-
values
-
valuesAsList
-
valuesAsIntVLA
-
valuesAsArray
-
trim
Rehashes the map, making the table as small as possible.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.
If the table size is already the minimum possible, this method does nothing.
- Returns:
- true if there was enough memory to trim the map.
- See Also:
trim(int)
-
trim
Rehashes this map if the table is too large.Let N be the smallest table size that can hold
max(n,
entries, still satisfying the load factor. If the current table size is smaller than or equal to N, this method does nothing. Otherwise, it rehashes this map in a table of size N.size()
)This method is useful when reusing maps. Clearing a map leaves the table size untouched. If you are reusing a map many times, you can call this method with a typical size to avoid keeping around a very large table just because of a few large transient maps.
- Parameters:
n
- the threshold for the trimming.- Returns:
- true if there was enough memory to trim the map.
- See Also:
trim()
-
rehash
Rehashes the map.This method implements the basic rehashing strategy, and may be overriden by subclasses implementing different rehashing strategies (e.g., disk-based rehashing). However, you should not override this method unless you understand the internal workings of this class.
- Parameters:
newN
- the new size
-
clone
Returns a deep copy of this map.This method performs a deep copy of this MultiArrangement; the data stored in the map, however, is not cloned. Note that this makes a difference only for object keys.
-
hashCode
Returns a hash code for this map. This method overrides the generic method provided by the superclass. Sinceequals()
is not overriden, it is important that the value returned by this method is the same value as the one returned by the overriden method. -
maxFill
Returns the maximum number of entries that can be filled before rehashing.- Parameters:
n
- the size of the backing array.f
- the load factor.- Returns:
- the maximum number of entries before rehashing.
-
maxFill
Returns the maximum number of entries that can be filled before rehashing.- Parameters:
n
- the size of the backing array.f
- the load factor.- Returns:
- the maximum number of entries before rehashing.
-
arraySize
Returns the least power of two smaller than or equal to 230 and larger than or equal toMath.ceil( expected / f )
.- Parameters:
expected
- the expected number of elements in a hash table.f
- the load factor.- Returns:
- the minimum possible size for a backing array.
- Throws:
IllegalArgumentException
- if the necessary size is larger than 230.
-
toString
-
equals
-
getAt
Gets the value at the given index in the iteration order in constant time (random-access).- Parameters:
idx
- the index in the iteration order of the value to fetch- Returns:
- the value at the index, if the index is valid, otherwise the default return value
-
keyAt
Gets the key at the given index in the iteration order in constant time (random-access).- Parameters:
idx
- the index in the iteration order of the key to fetch- Returns:
- the key at the index, if the index is valid, otherwise null
-
removeAt
Removes the key and value at the given index in the iteration order in not-exactly constant time (though it still should be efficient).- Parameters:
idx
- the index in the iteration order of the key and value to remove- Returns:
- the key removed, if there was anything removed, or null otherwise
-
addAt
Equivalent toadd(Object)
, except that it can place k at any point in the ordering (shifting up later entries and changing their values to match their new positions in the ordering).- Parameters:
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)k
- the key to add into this MultiArrangement; its value will be idx- Returns:
- the previous position in the ordering that k had if already present, the previous size of the MultiArrangement if k was just added now, or -1 if idx is invalid
-
randomKey
Gets a random key from this MultiArrangement in constant time, using the given IRNG to generate a random number.- Parameters:
rng
- used to generate a random index for a key- Returns:
- a random key from this MultiArrangement, or null if this is empty
-
shuffle
Randomly alters the iteration order for this MultiArrangement using the given IRNG to shuffle.- Parameters:
rng
- used to generate a random ordering- Returns:
- this for chaining
-
reorder
Given an array or varargs of replacement indices for this MultiArrangement's iteration order, reorders this so the first item in the returned version is the same asgetAt(ordering[0])
(with some care taken for negative or too-large indices), the second item in the returned version is the same asgetAt(ordering[1])
, etc.
Negative indices are considered reversed distances from the end of ordering, so -1 refers to the same index asordering[ordering.length - 1]
. If ordering is smaller thansize()
, only the indices up to the length of ordering will be modified. If ordering is larger thansize()
, only as many indices will be affected assize()
, and reversed distances are measured from the end of this Map's entries instead of the end of ordering. Duplicate values in ordering will produce duplicate values in the returned Map.
This method modifies this MultiArrangement in-place and also returns it for chaining.- Parameters:
ordering
- an array or varargs of int indices, where the nth item in ordering changes the nth item in this Map to have the value currently in this Map at the index specified by the value in ordering- Returns:
- this for chaining, after modifying it in-place
-
alter
Swaps a key, original, for another key, replacement, while keeping replacement at the same point in the iteration order as original and keeping it associated with the same value (which also keeps its iteration index).- Parameters:
original
- the key to find and swap outreplacement
- the key to replace original with- Returns:
- the value associated with original before, and replacement now
-
getArray
-
getArray
-
getMany
-
keysAt
-
keysAt
-
take
Produces a copy of this MultiArrangement, but only using up to the given amount of items to take. Does a shallow copy of individual keys, so the references will be shared.- Parameters:
amount
- the number of items to copy from this MultiArrangement; will copy all items if greater than size- Returns:
- a new MultiArrangement with up to amount items copied from this into it.
-
positionOf
-
swap
Swaps the positions in the ordering for the given items, if they are both present. Returns true if the ordering changed as a result of this call, or false if it stayed the same (which can be because left or right was not present, or because left and right are the same reference (so swapping would do nothing)).- Parameters:
left
- an item that should be present in this OrderedSetright
- an item that should be present in this OrderedSet- Returns:
- true if this OrderedSet changed in ordering as a result of this call, or false otherwise
-
swapIndices
Swaps the given indices in the ordering, if they are both ints between 0 and size. Returns true if the ordering changed as a result of this call, or false if it stayed the same (which can be because left or right referred to an out-of-bounds index, or because left and right are equal (so swapping would do nothing)).
-