Every now and then, you may want to collapse multiple values into a `long`

, to use as a key for a `Map`

, for example.

The following code is an example of collapsing three `int`

s into one `long`

. Obvious care should be taken here: three `int`

s don’t actually *fit* into one `long`

, so the excess bits are just discarded. If we do this, we can afford to use the lowest 20 bits, plus the sign bit, leaving us with a data range of 1,048,576 to -1,048,575.

For each `int`

we take the lower 20 bits:

input & 0xfffff

…and the sign bit, which we move to position 21:

(input & Integer.MIN_VALUE) >>> 11

and then combine the two:

(input & 0xfffff | (input & Integer.MIN_VALUE) >>> 11)

Now, we repeat the process for all our inputs and put them in our `long`

, shifting two of them by 21 and 42 respectively so they don’t overlap:

long l = 0; l |= (long)(input1 & 0xfffff | (input1 & Integer.MIN_VALUE) >>> 11); l |= (long)(input2 & 0xfffff | (input2 & Integer.MIN_VALUE) >>> 11) << 21; l |= (long)(input3 & 0xfffff | (input3 & Integer.MIN_VALUE) >>> 11) << 42;

If you were to combined a higher amount of things with less bits, this loop version will probably be more concise, courtesy of Maldivia:

public static long pack(int i1, int i2, int i3) { int[] data = new int[] { i1, i2, i3 }; long l = 0; for (int i = 0; i < 3; i++) { l |= (long)(data[i] & 0xfffff | (data[i] & Integer.MIN_VALUE) >>> 11) << (i * 21); } return l; }

And to unpack the `long`

back into pieces:

public static int[] unpack(long l) { int[] res = new int[3]; for (int i = 0; i < 3; i++) { res[i] = (int) (l & 0xfffff); if ((l & 0x100000) != 0) { res[i] |= 0xfff00000; } l >>>= 21; } return res; }

Comments on this entry are closed.