Reputation: 20069
For a project I'm working on, I try to create a multi-dimensional pivot on large data sets. I have all the keys I want to use as int
s, so basically, I want to return a set of
( int1, int2, int3, .. intN ) -> (Aggregate1, Aggregate2, ... , AggregateM)
I cannot use a N-dimensional array, as it might get huge and probably will be sparse. I've looked a Trove, but they do not have a Multi-key map. Apache commons has a multi-key map, but that is for Objects
; that would probably work, but seems less interesting as the int
s will get auto-boxed to Integers
and vice versa.
Does anyone know of a primitive multi-key map implementation? (That maps to objects?)
Or, does anyone have great hints, maybe there is a better approach to my problem?
[edit] Insertion time is less interesting, I need the performance on the lookup, as the map will be heavily used to lookup values.
[edit2]
Thanks for all the answers. My implemenation choice is a custom class containing an int[], immutable so the hashcode
can be calculated on construction time.
private static class MultiIntKey
{
int[] ints;
private int hashCode;
MultiIntKey( int[] ints )
{
this.ints = ints;
this.hashCode = Arrays.hashCode( this.ints );
}
@Override
public int hashCode()
{
return this.hashCode;
}
@Override
public boolean equals( Object obj )
{
if ( this == obj )
{
return true;
}
if ( obj == null )
{
return false;
}
if ( this.getClass() != obj.getClass() )
{
return false;
}
MultiIntKey other = (MultiIntKey) obj;
if ( this.hashCode != other.hashCode )
{
return false;
}
if ( !Arrays.equals( this.ints, other.ints ) )
{
return false;
}
return true;
}
}
Upvotes: 1
Views: 1052
Reputation: 4598
A string key with ( int1, int2, int3, .. intN ) == (int1 + "" int2 + ""..).intern()
so all keys from same table via intern so very few new objects. Need to use intern every time you want to the key as its dynamic.
Upvotes: 0
Reputation: 46482
Apache commons has a multi-key map, but that is for Objects; that would probably work, but seems less interesting as the ints will get auto-boxed to Integers and vice versa.
Sure, it makes no sense to use N
objects while trying to avoid one.
int
or long
.TIntObjectMap<TIntObjectMap<Value>>
using trove4j, possibly with more nesting.4*N
. A map hash a big overhead anyway...If your map is immutable, go for Guava's ImmutableMap
. Look at Guava Table
, it's 2D only, but it may help to save a bit.
Only if you're sure you need to optimize a lot (have you done some benchmarking or profiling?) and you don't need a fully fledged map, think about your own implementation based on some int[]
, where you place all the keys in sequence. Most probably you'll find out that it wasn't worth it, but it's a good exercise. :D
Upvotes: 4
Reputation: 44404
Each key can be:
IntBuffer.wrap(new int[] { value1, value2, value3 })
IntBuffer's hashCode, equals, and compareTo methods depend on its contents, so they will work as HashMap or TreeMap keys. (Technically those methods depend on the remaining elements in the buffer, so just make sure you never change the position or limit of any of the IntBuffers you create.)
The one caveat is that order matters: IntBuffer.wrap(new int[] { 1, 2 })
is not equal to IntBuffer.wrap(new int[] { 2, 1 })
.
Upvotes: 1
Reputation: 35096
Easiest ways to do:
Upvotes: -1