I have a requirement in which I need to map multiple determinants to values.
- Each set of determinants in a given job execution is guaranteed to be unique. The value to be determined doesn't have to be unique but it probably is. 
- Depending on the input to the job execution, this could be either one key, or the combination of two keys, or the combination of - nkeys that will be mapped to a single value. In practice this- nwill probably be limited to no more than 5, although it is possible it could exceed that.
- Each job execution will have a set number of determinants for all inputs (I.e., all inputs will have either 2 determinants, 3 determinants, or n determinants, and will not have a mix). 
One key example: foo --> bar
Two keys: foo, bar --> baz
Three keys: foo, bar, baz --> hai
Prior to this, the requirement was that I would only ever map two values to another value. I created an immutable Key class with two member variables and the appropriate override of equals and hashCode. 
public class Key {
    String determinant0;
    String determinant1;
    public Key(String d0, d1) {
        determinant0 = d0;
        determinant1 = d1;
    }
    // ..
} 
However, now that I may be dealing with n number of values, I want to take a look at using a list as the key.
Map<List, String> map = new HashMap<List, String>();
map.put(Arrays.asList("foo", "bar", "baz"), "hai");
String determined = map.get(Arrays.AsList("foo","bar","baz"));
assert (determined.equals("hai"));
This question reminds me that it is bad to use a mutable object (like a List) as a key in a map. However, in my application, the key is only set once and is never altered. Here is an alternative from this question that forces it to be immutable:
HashMap<List<String>, String> map;
map.put(
    // unmodifiable so key cannot change hash code
    Collections.unmodifiableList(Arrays.asList("foo", "bar", "baz")),
    "hai"
);
In addition, I could always make a class like the following to prevent mutations on the list:
public class Key {
    List<String> determinants;
    public Key(List<String> determinants) {
        this.determinants = determinants
    }
    @Override
    public boolean equals(Object obj) {
        //...
    }
    @Override
    public int hashCode() {
        //...
    }
}
Key key = new Key(Arrays.asList("foo","bar","baz"));
Using a plain array as the key won't work, because an array's equal method only checks for identity:
Map<String[], String> map = new HashMap<String[], String>();
String[] key = new String[]{"foo", "bar", "baz"}
map.put(key, "hai");
System.out.println(map.get(key)); // null
That could be fixed by the following:
public class Key {
    String[] determinants;
    public Key(String... determinants) {
        this.determinants = determinants;
    }
    @Override
    public boolean equals(Object obj) {
        //...
    }
    @Override
    public int hashCode() {
        //...
    }
}
How about concatting all the determinants together in a string?
public class Key {
    String hash = "";
    public Key(String... determinants) {
        for (String determinant : determinants) {
            hash += determinant + "_";
        }
    }
    @Override
    public boolean equals(Object obj) {
        //...
    }
    @Override
    public int hashCode() {
        //...
    }
}
Which one of these solutions (or another one that I did not propose) is the best suited for these requirements?
 
     
    