Since no one has stepped forward and given a full answer to your questions, I'll give it a shot:
Using Map< ArrayList<String> , String >
The problem with this approach is that ArrayList<String>
is mutable. See this example for instance:
Map<ArrayList<String>, String> map = new HashMap<>();
ArrayList<String> l = new ArrayList<>();
l.add("a");
l.add("b");
map.put(l, "Hello");
System.out.println(map.get(l)); // "Hello";
l.add("c"); // Mutate key.
System.out.println(map.get(l)); // null (value lost!)
Further reading:
Using Map< int[] , String >
This is possible, but may be confusing because two arrays may seem equal, but not .equals
each other. Consider the following example:
Map<int[], String> map = new HashMap<>();
int[] arr1 = { 1, 2 };
map.put(arr1, "Hello");
int[] arr2 = { 1, 2 };
System.out.println(map.get(arr2)); // null, since arr1.equals(arr2) == false
So, to retrieve previously inserted values, you need to use the same instance as key. The above example only works if you use map.get(arr1)
.
So what to do?
You can, as you suggest, roll your own data structure that keeps track of the mapping in private data structures. You could for instance use a Map<List<...>, String>
as a backing structure but make sure that you never mutate the keys you use in that map (for instance by keeping the map private and never ever publish references to the List
-keys).
If you know the sizes of your keys in advance, you can use nested maps, as follows: Map<String, Map<String, String>>
.
You can use a third party collection library such as Guava or Apache Commons. They have a data structures called Table
resp. MultiKeyMap
which both seems to match your requirements.
You can create a new, immutable, key object as suggested by @dasblinkenlight. (A word of caution; this is safe just because String
is immutable!) The code can be simplified slightly as follows:
final class StringTuple {
private String[] vals;
public StringTuple(String... vals) {
this.vals = vals.clone();
}
public int hashCode() {
return Arrays.hashCode(vals);
}
public boolean equals(Object obj) {
return (obj instanceof StringTuple)
&& Arrays.equals(vals, ((StringTuple) obj).vals);
}
}