Alternatives to 2D Arrays in Java
I have a lookup table that should be accessed by two separate key values. One ugly way to do this is:
int[][] myArray = new int[256][256];
myArray[key1][key2] = 25;
where key1 and key2 are keys that were previously generated dynamically. But this is rather ugly. It seems that a better way to do this would be to use a Map, but those require a single 开发者_运维知识库key, not two. Java doesn't natively support tuples, so what should I use instead? (It also seems awkward to use an array as the key).
EDIT: The reason I say that this isn't particularly pretty is that my array is actually referenced by character values, not integers. They could be used interchangeably, but the responses to my previous question seem to suggest otherwise:
2D Array in Java, Indexed by Characters
What's so ugly about that? That's about as simple as 2D matrices can be in Java, and it's quick, too.
If you really want to use a map, just defined your own Tuple
class to use as a key - but be sure that you override equals()
and hashCode()
correctly! I'd recommend implementing an immutable Tuple
class because using mutable objects as map keys can cause serious issues.
Tuple.java
package q5128376;
import java.util.Arrays;
public class Tuple<T>
{
private T[] values;
private int hashCode;
private Tuple(T... values)
{
this.values = values;
this.hashCode = hashCode(values);
}
public static <T> Tuple<T> create(T... values)
{
return new Tuple<T>(values);
}
private static <T> int hashCode(T... values)
{
return 31 * Arrays.hashCode(values);
}
@Override
public int hashCode()
{
return hashCode;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (!(obj instanceof Tuple<?>)) return false;
Tuple<?> other = (Tuple<?>) obj;
if (!Arrays.equals(values, other.values)) return false;
return true;
}
}
Your solution does not seem very ugly to me... It's very fast, at the expense of a little memory usage (64 K ints).
An alternative would be to define a Pair
class to use as a key for a map.
Yet another solution would be to define a map that maps ints to a map mapping ints to int values:
Map<Integer, Map<Integer, Integer>> map;
However, this would require the creation of a lot of map objects.
The best approach depends on how sparse your lookup table is.
I agree with ChrisJ that your 2 dimensional array is not bad at all.
You could have a Map of a Map, like
Map<Integer, Map<Integer, Integer>> myMap;
But that can get even more ugly than your 2d array idea.
Alternatively, you could convert two int keys into one String key, like
Map<String, Integer> myMap = new HashMap<String, Integer>();
int key1 = 3;
int key2 = 4;
int value = 25;
myMap.put(key1 + "/" + key2, value);
But I recommend going with the solution you have, if you can guarentee that the highest value for either key is 255.
精彩评论