Package squidpony.squidmath
Class BundleBiMap<E,S>
java.lang.Object
squidpony.squidmath.BundleBiMap<E,S>
public class BundleBiMap<E,S> extends Object
An ordered bidirectional map-like data structure, with "bundles" of unique E (for Element) keys and unique S (for
Single) keys updated together like a map that can be queried by E key bundles, S keys, or int indices, as well as
like a multimap that can be queried by lone E keys. A bundle can be specified as a Collection of E values, an array
of E values, or in two parts as either of the above given to a BundleBiMap method along with an int array that can
represent variations on E keys (e.g. some quantity for an E value that permits different amounts to be passed with
the unique E values to getS and have it yield a different S for a, say, 1 Foo and 1 Bar vs. 2 Foo and 3 Bar). This
allows an intended purpose for this class as a way to describe crafting recipes that may need various amounts of an
item to be mixed in, and since the quantities are optional, it can still be used to group multiple E keys with S
keys. The multimap property allows you to use an E element key to get all of the S keys that are associated with a
bundle that contains that E key (you can also get the ordering indices for those S keys, which you can use to get the
full bundle if you want).
Does not implement any interfaces that you would expect for a data structure, because almost every method it has needs to specify whether it applies to E or S items, or otherwise doesn't fit a normal Collection-like interface's requirements.
Closely related to Arrangement, K2, and K2V1 in implementation.
Created by Tommy Ettinger on 4/26/2017.
Does not implement any interfaces that you would expect for a data structure, because almost every method it has needs to specify whether it applies to E or S items, or otherwise doesn't fit a normal Collection-like interface's requirements.
Closely related to Arrangement, K2, and K2V1 in implementation.
Created by Tommy Ettinger on 4/26/2017.
-
Constructor Summary
Constructors Constructor Description BundleBiMap()
Constructs an empty BundleBiMap.BundleBiMap(int expected)
Constructs a BundleBiMap with the expected number of indices to hold (the number of bundles and number of S items is always the same, and this will be more efficient if expected is greater than that number).BundleBiMap(int expected, float f)
Constructs a BundleBiMap with the expected number of indices to hold (the number of bundles and number of S items is always the same, and this will be more efficient if expected is greater than that number) and the load factor to use, between 0.1f and 0.8f usually (using load factors higher than 0.8f can cause problems).BundleBiMap(BundleBiMap<E,S> other)
Constructs a BundleBiMap using another BundleBiMap to copy. -
Method Summary
Modifier and Type Method Description BundleBiMap<E,S>
alterB(S past, S future)
Changes an existing S key,past
, to another S key,future
, if past exists in this BundleBiMap and future does not yet exist in this BundleBiMap.BundleBiMap<E,S>
alterSingleAt(int index, S future)
Changes the S key atindex
to another S key,future
, if index is valid and future does not yet exist in this K2.boolean
containsElement(E element)
Returns true if this contains the E, element, in any of its bundles of E keys.boolean
containsIndex(int index)
Returns true if index is between 0 (inclusive) andsize()
(exclusive), or false otherwise.boolean
containsSingle(S single)
Returns true if this contains the S, single, in its collection of S items.OrderedSet<E>
elementsFromCode(int[][] bundle)
Given a coded bundle as produced by some methods in this class, decodes the elements part of the bundle and returns it as a newly-allocated OrderedSet of E element keys.int
elementSize()
Gets the total number of unique E element keys across all bundles in this BundleBiMap.OrderedSet<E>
getBundleElements(S single)
Given an S key to look up, gets a (newly-allocated) OrderedSet of E element keys corresponding to that S key.OrderedSet<E>
getBundleElementsAt(int index)
Given an index to look up, gets a (newly-allocated) OrderedSet of E element keys in the bundle at that index.int[]
getBundleVariation(S single)
Given an S key to look up, gets a (newly-allocated) int array that is equivalent to the variation part of the bundle corresponding to single.int[]
getBundleVariationAt(int index)
Given an index to look up, gets a (newly-allocated) int array that is equivalent to the variation part of the bundle present at that index.int[][]
getCode(S single)
Given an S key to look up, gets a 2D int array representing the key's matching bundle.int[][]
getCodeAt(int index)
Given an index to look up, gets a 2D int array representing the bundle at that index.OrderedSet<E>
getElementOrderedSet()
To be called sparingly, since this allocates a new OrderedSet instead of reusing one.SortedSet<E>
getElementSet()
Gets and caches the individual E keys as a Collection that implements SortedSet (and so also implements Set).OrderedSet<int[][]>
getManyCoded(E element)
Given an E element key that could be used in one or more bundles this uses, gets all bundles in this object that contain the given element, as coded 2D int arrays.int[]
getManyIndices(E element)
Given an E element key that could be used in one or more bundles this uses, gets all indices in the ordering that contain a bundle with that element.OrderedSet<S>
getManySingles(E element)
Given an E element key that could be used in one or more bundles this uses, finds all S single keys corresponding to bundles that contain the given element.S
getSingle(E[] e)
Given a bundle of E keys as an array with no variation, gets the matching S key for that bundle, or null if there is none.S
getSingle(E[] e, int[] variations)
Given a bundle of E keys as an array with an int array variation, gets the matching S key for that bundle, or null if there is none.S
getSingle(Collection<? extends E> e)
Given a bundle of E keys as a Collection with no variation, gets the matching S key for that bundle, or null if there is none.S
getSingle(Collection<? extends E> e, int[] variations)
Given a bundle of E keys as a Collection with an int array variation, gets the matching S key for that bundle, or null if there is none.S
getSingleAt(int index)
Given an int index, finds the associated S key (using index as a point in the ordering).S
getSingleCoded(int[][] code)
Given a bundle as a coded 2D int array, gets the matching S key for that bundle, or null if there is none.OrderedSet<S>
getSingleOrderedSet()
To be called sparingly, since this allocates a new OrderedSet instead of reusing one.SortedSet<S>
getSingleSet()
Gets and caches the S single keys as a Collection that implements SortedSet (and so also implements Set).int
indexOfSingle(S single)
Gets (in near-constant time) the index of the given S single key in the ordering.boolean
isEmpty()
Iterator<E>
iteratorElements()
Creates a new iterator over the individual E element keys this holds, with a larger total count the iterator may yield thansize()
in most cases (it should be equal toelementSize()
), and in no particular order (though the order should be stable across versions and platforms, no special means are provided to further control the order).Iterator<S>
iteratorSingles()
Creates a new iterator over the S single keys this holds.boolean
put(E[] e, int[] variation, S s)
Adds a bundle of E keys, mixed with an int array of variations, and a S key at the same point in the ordering (the end) to this BundleBiMap.boolean
put(E[] e, S s)
Adds a bundle of E keys and a S key at the same point in the ordering (the end) to this BundleBiMap.boolean
put(Collection<? extends E> e, int[] variation, S s)
Adds a bundle of E keys, mixed with an int array of variations, and a S key at the same point in the ordering (the end) to this BundleBiMap.boolean
put(Collection<? extends E> e, S s)
Adds a bundle of E keys and a S key at the same point in the ordering (the end) to this BundleBiMap.boolean
putAll(Iterable<? extends Collection<? extends E>> aKeys, Iterable<? extends S> bKeys)
Puts all unique E and S keys inaKeys
andbKeys
into this K2 at the end.boolean
putAll(BundleBiMap<? extends E,? extends S> other)
Puts all unique E and S keys inother
into this K2, respecting other's ordering.E
randomElement(IRNG random)
Gets a random E from this BundleBiMap's individual elements using the given IRNG.S
randomSingle(IRNG random)
Gets a random S from this BundleBiMap using the given IRNG.BundleBiMap<E,S>
reorder(int... ordering)
Reorders this BundleBiMap usingordering
, which has the same length as this object'ssize()
and can be generated withArrayTools.range(int)
(which, if applied, would produce no change to the current ordering),IRNG.randomOrdering(int)
(which gives a random ordering, and if applied immediately would be the same as callingshuffle(IRNG)
), or made in some other way.BundleBiMap<E,S>
shuffle(IRNG rng)
Generates a random ordering with rng and applies the same ordering to all kinds of keys this has; they will maintain their current association to other keys but their ordering/indices will change.S
singleAt(int index)
Given an index to look up, gets the S key present at that position in the ordering.int
size()
Gets the total number of bundle-to-single pairs in this BundleBiMap.int[]
variationFromCode(int[][] bundle)
Given a coded bundle as produced by some methods in this class, decodes the variation part of the bundle, if present, and returns it as a newly-allocated 1D int array.
-
Constructor Details
-
BundleBiMap
public BundleBiMap()Constructs an empty BundleBiMap. -
BundleBiMap
Constructs a BundleBiMap with the expected number of indices to hold (the number of bundles and number of S items is always the same, and this will be more efficient if expected is greater than that number).- Parameters:
expected
- how many bundle-to-single pairings this is expected to hold
-
BundleBiMap
Constructs a BundleBiMap with the expected number of indices to hold (the number of bundles and number of S items is always the same, and this will be more efficient if expected is greater than that number) and the load factor to use, between 0.1f and 0.8f usually (using load factors higher than 0.8f can cause problems).- Parameters:
expected
- the amount of indices (the count of bundles is the same as the count of S items) this should holdf
- the load factor, probably between 0.1f and 0.8f
-
BundleBiMap
Constructs a BundleBiMap using another BundleBiMap to copy.- Parameters:
other
- the other BundleBiMap to copy
-
-
Method Details
-
containsElement
Returns true if this contains the E, element, in any of its bundles of E keys.- Parameters:
element
- the E to check the presence of in all bundles- Returns:
- true if element is present in this; false otherwise
-
containsSingle
Returns true if this contains the S, single, in its collection of S items.- Parameters:
single
- the S to check the presence of- Returns:
- true if single is present in this; false otherwise
-
containsIndex
Returns true if index is between 0 (inclusive) andsize()
(exclusive), or false otherwise.- Parameters:
index
- the index to check- Returns:
- true if index is a valid index in the ordering of this BundleBiMap
-
getSingleAt
Given an int index, finds the associated S key (using index as a point in the ordering).- Parameters:
index
- an int index into this BundleBiMap- Returns:
- the S object with index for its position in the ordering, or null if index was invalid
-
randomElement
Gets a random E from this BundleBiMap's individual elements using the given IRNG.- Parameters:
random
- generates a random index to get an E with- Returns:
- a randomly chosen E, or null if this is empty
-
randomSingle
Gets a random S from this BundleBiMap using the given IRNG.- Parameters:
random
- generates a random index to get a S with- Returns:
- a randomly chosen S, or null if this is empty
-
alterB
Changes an existing S key,past
, to another S key,future
, if past exists in this BundleBiMap and future does not yet exist in this BundleBiMap. This will retain past's point in the ordering for future, so the associated other key(s) will still be associated in the same way.- Parameters:
past
- a S key, that must exist in this BundleBiMap's S keys, and will be changedfuture
- a S key, that cannot currently exist in this BundleBiMap's S keys, but will if this succeeds- Returns:
- this for chaining
-
alterSingleAt
Changes the S key atindex
to another S key,future
, if index is valid and future does not yet exist in this K2. The position in the ordering for future will be the same as index, and the same as the key this replaced, if this succeeds, so the other key(s) at that position will still be associated in the same way.- Parameters:
index
- a position in the ordering to change; must be at least 0 and less thansize()
future
- a S key, that cannot currently exist in this BundleBiMap's S keys, but will if this succeeds- Returns:
- this for chaining
-
put
Adds a bundle of E keys and a S key at the same point in the ordering (the end) to this BundleBiMap. Neither parameter can be present in this collection before this is called.- Parameters:
e
- an array of E keys to add; the array cannot already be present, nor can it be nulls
- e S key to add; cannot already be present- Returns:
- true if this collection changed as e result of this call
-
put
Adds a bundle of E keys, mixed with an int array of variations, and a S key at the same point in the ordering (the end) to this BundleBiMap. Neither the S key nor the bundle (effectively, the pair of e and variation) can be present in this collection before this is called.- Parameters:
e
- an array of E keys to add; the array cannot already have been inserted with an equivalent variation, nor can it be nullvariation
- an int array that can be used to make a different version of e, i.e. the same things at different quantities; cannot be nulls
- e S key to add; cannot already be present- Returns:
- true if this collection changed as e result of this call
-
put
Adds a bundle of E keys and a S key at the same point in the ordering (the end) to this BundleBiMap. Neither parameter can be present in this collection before this is called.- Parameters:
e
- an array of E keys to add; the array cannot already be present, nor can it be nulls
- e S key to add; cannot already be present- Returns:
- true if this collection changed as e result of this call
-
put
Adds a bundle of E keys, mixed with an int array of variations, and a S key at the same point in the ordering (the end) to this BundleBiMap. Neither the S key nor the bundle (effectively, the pair of e and variation) can be present in this collection before this is called.- Parameters:
e
- an array of E keys to add; the array cannot already have been inserted with an equivalent variation, nor can it be nullvariation
- an int array that can be used to make a different version of e, i.e. the same things at different quantities; cannot be nulls
- e S key to add; cannot already be present- Returns:
- true if this collection changed as e result of this call
-
putAll
public boolean putAll(Iterable<? extends Collection<? extends E>> aKeys, Iterable<? extends S> bKeys)Puts all unique E and S keys inaKeys
andbKeys
into this K2 at the end. If an E in aKeys or a S in bKeys is already present when this would add one, this will not put the E and S keys at that point in the iteration order, and will place the next unique E and S it finds in the arguments at that position instead.- Parameters:
aKeys
- an Iterable or Collection of E keys to add; should all be unique (like a Set)bKeys
- an Iterable or Collection of S keys to add; should all be unique (like a Set)- Returns:
- true if this collection changed as a result of this call
-
putAll
Puts all unique E and S keys inother
into this K2, respecting other's ordering. If an E or a S in other is already present when this would add one, this will not put the E and S keys at that point in the iteration order, and will place the next unique E and S it finds in the arguments at that position instead.- Parameters:
other
- another K2 collection with the same E and S types- Returns:
- true if this collection changed as a result of this call
-
getCode
Given an S key to look up, gets a 2D int array representing the key's matching bundle. The bundle is likely to use a representation for the first sub-array that will be meaningless without internal information from this BundleBiMap, but the second sub-array, if present, should match the variation supplied with that bundle toput(Object[], int[], Object)
orput(Collection, int[], Object)
.
This method copies the 2D int array it returns, so modifying it won't affect the original BundleBiMap.- Parameters:
single
- a S key to look up- Returns:
- a copied 2D int array that represents a bundle, or null if single is not present in this
-
getCodeAt
Given an index to look up, gets a 2D int array representing the bundle at that index. The bundle is likely to use a representation for the first sub-array that will be meaningless without internal information from this BundleBiMap, but the second sub-array, if present, should match the variation supplied with that bundle toput(Object[], int[], Object)
orput(Collection, int[], Object)
.
This method copies the 2D int array it returns, so modifying it won't affect the original BundleBiMap.- Parameters:
index
- an int index to look up- Returns:
- a 2D int array that represents a bundle, or null if index is out of bounds
-
singleAt
Given an index to look up, gets the S key present at that position in the ordering.- Parameters:
index
- an int index to look up- Returns:
- a 2D int array that represents a bundle, or null if index is out of bounds
-
getSingle
Given a bundle of E keys as an array with no variation, gets the matching S key for that bundle, or null if there is none.- Parameters:
e
- an array of E- Returns:
- the S key that corresponds to the given bundle, e
-
getSingle
Given a bundle of E keys as an array with an int array variation, gets the matching S key for that bundle, or null if there is none.- Parameters:
e
- an array of E element keysvariations
- an int array that should match an int array used as a variation parameter to put- Returns:
- the S key that corresponds to the given bundle, e combined with variations
-
getSingle
Given a bundle of E keys as a Collection with no variation, gets the matching S key for that bundle, or null if there is none.- Parameters:
e
- a Collection of E element keys (each key can be an E or an instance of any subclass of E)- Returns:
- the S key that corresponds to the given bundle, e
-
getSingle
Given a bundle of E keys as a Collection with an int array variation, gets the matching S key for that bundle, or null if there is none.- Parameters:
e
- a Collection of E element keys (each key can be an E or an instance of any subclass of E)variations
- an int array that should match an int array used as a variation parameter to put- Returns:
- the S key that corresponds to the given bundle, e combined with variations
-
getSingleCoded
Given a bundle as a coded 2D int array, gets the matching S key for that bundle, or null if there is none. The code parameter should be obtained from one of the methods that specifically returns that kind of 2D array, since the code uses internal information to efficiently represent a bundle.- Parameters:
code
- a 2D int array representing a bundle that should have been obtained directly from this object- Returns:
- the S key that corresponds to the given coded bundle
-
indexOfSingle
Gets (in near-constant time) the index of the given S single key in the ordering.- Parameters:
single
- a S single key to look up- Returns:
- the position in the ordering of single
-
elementsFromCode
Given a coded bundle as produced by some methods in this class, decodes the elements part of the bundle and returns it as a newly-allocated OrderedSet of E element keys.- Parameters:
bundle
- a coded bundle as a 2D int array- Returns:
- an OrderedSet of E element keys corresponding to the data coded into bundle
-
variationFromCode
Given a coded bundle as produced by some methods in this class, decodes the variation part of the bundle, if present, and returns it as a newly-allocated 1D int array. If there is no variation in the given coded bundle, this returns null.- Parameters:
bundle
- a coded bundle as a 2D int array- Returns:
- an OrderedSet of E element keys corresponding to the data coded into bundle
-
getBundleElements
Given an S key to look up, gets a (newly-allocated) OrderedSet of E element keys corresponding to that S key. If a variation is part of the bundle, it will not be present in this, but a copy can be retrieved withgetBundleVariation(Object)
.- Parameters:
single
- a S key to look up- Returns:
- an OrderedSet of the E elements used in the bundle that corresponds to single, or null if invalid
-
getBundleVariation
Given an S key to look up, gets a (newly-allocated) int array that is equivalent to the variation part of the bundle corresponding to single. If there is no variation in the corresponding bundle, then this returns null. To get the E elements that are the main part of a bundle, you can usegetBundleElements(Object)
.- Parameters:
single
- a S key to look up- Returns:
- an int array copied from the variation part of the bundle that corresponds to single, or null if invalid
-
getBundleElementsAt
Given an index to look up, gets a (newly-allocated) OrderedSet of E element keys in the bundle at that index. If a variation is part of the bundle, it will not be present in this, but a copy can be retrieved withgetBundleVariationAt(int)
.- Parameters:
index
- an int position in the ordering to look up- Returns:
- an OrderedSet of the E elements used in the bundle present at index, or null if invalid
-
getBundleVariationAt
Given an index to look up, gets a (newly-allocated) int array that is equivalent to the variation part of the bundle present at that index. If there is no variation in the corresponding bundle, then this returns null. To get the E elements that are the main part of a bundle, you can usegetBundleElementsAt(int)
.- Parameters:
index
- an int position in the ordering to look up- Returns:
- an int array copied from the variation part of the bundle present at index, or null if invalid
-
getManySingles
Given an E element key that could be used in one or more bundles this uses, finds all S single keys corresponding to bundles that contain the given element. Thus, if E was String and this BundleBiMap contained ["Copper", "Tin"] mapped to "Bronze" and ["Zinc", "Copper"] mapped to "Brass", then calling this method with "Copper" would get an OrderedSet that contains ["Bronze", "Brass"].- Parameters:
element
- an E element key to look up (probably a component of one or more bundles)- Returns:
- an OrderedSet of all S keys where the given element is part of the bundle corresponding to that S key, or null if E does not match anything
-
getManyCoded
Given an E element key that could be used in one or more bundles this uses, gets all bundles in this object that contain the given element, as coded 2D int arrays. These coded bundles can be given toelementsFromCode(int[][])
andvariationFromCode(int[][])
to get usable information from them.- Parameters:
element
- an E element key to look up (probably a component of one or more bundles)- Returns:
- an OrderedSet of all coded 2D int array bundles that contain the given element, or null if E is not in any bundles
-
getManyIndices
Given an E element key that could be used in one or more bundles this uses, gets all indices in the ordering that contain a bundle with that element. From such an index, you can usegetSingleAt(int)
to get the S key at that position,getBundleElementsAt(int)
to get the E element keys at that position,getBundleVariationAt(int)
to get the possible variation at that position, orgetCodeAt(int)
to get the coded bundle at that position.- Returns:
- an OrderedSet of all coded 2D int array bundles that contain the given element, or null if E is not in any bundles
-
reorder
Reorders this BundleBiMap usingordering
, which has the same length as this object'ssize()
and can be generated withArrayTools.range(int)
(which, if applied, would produce no change to the current ordering),IRNG.randomOrdering(int)
(which gives a random ordering, and if applied immediately would be the same as callingshuffle(IRNG)
), or made in some other way. If you already have an ordering and want to make a different ordering that can undo the change, you can useArrayTools.invertOrdering(int[])
called on the original ordering. The effects of this method, if called with an ordering that has repeat occurrences of an int or contains ints that are larger than its size should permit, are undefined other than the vague definition of "probably bad, unless you like crashes."- Parameters:
ordering
- an int array or vararg that must contain each int from 0 tosize()
- Returns:
- this for chaining
-
shuffle
Generates a random ordering with rng and applies the same ordering to all kinds of keys this has; they will maintain their current association to other keys but their ordering/indices will change.- Parameters:
rng
- an IRNG to produce the random ordering this will use- Returns:
- this for chaining
-
iteratorElements
Creates a new iterator over the individual E element keys this holds, with a larger total count the iterator may yield thansize()
in most cases (it should be equal toelementSize()
), and in no particular order (though the order should be stable across versions and platforms, no special means are provided to further control the order). The E keys are individual, not bundled, and duplicate keys should never be encountered even if an E key appears in many bundles.- Returns:
- a newly-created iterator over this BundleBiMap's individual (non-bundled) E keys
-
iteratorSingles
Creates a new iterator over the S single keys this holds. The total number of items this yields should be equal tosize()
. This method can be problematic for garbage collection if called very frequently; it may be better to access items by index (which also lets you access other keys associated with that index) usinggetSingleAt(int)
in a for(int i=0...) loop.- Returns:
- a newly-created iterator over this BundleBiMap's S keys
-
getElementSet
Gets and caches the individual E keys as a Collection that implements SortedSet (and so also implements Set).- Returns:
- the E keys as a SortedSet
-
getSingleSet
Gets and caches the S single keys as a Collection that implements SortedSet (and so also implements Set).- Returns:
- the S keys as a SortedSet
-
getElementOrderedSet
To be called sparingly, since this allocates a new OrderedSet instead of reusing one.- Returns:
- the E keys as an OrderedSet
-
getSingleOrderedSet
To be called sparingly, since this allocates a new OrderedSet instead of reusing one.- Returns:
- the S keys as an OrderedSet
-
size
Gets the total number of bundle-to-single pairs in this BundleBiMap.- Returns:
- the total number of bundle keys (equivalently, the number of single keys) in this object
-
elementSize
Gets the total number of unique E element keys across all bundles in this BundleBiMap. Usually not the same assize()
, and ordinarily a fair amount larger, though this can also be smaller.- Returns:
- the total number of unique E element keys in all bundles this contains
-
isEmpty
-