I need Java equivalent for following Python:
In [1]: d = {}
In [2]: k = ("x","2")
In [3]: d[k] = 1
In [4]: print d[("x","y")]
1
Python has tuples which are hashable. I tried following in Java unsuccessfully:
Map<String[], Integer> d = new HashMap<String[], Integer>();
String[] k = new String[]{"x", "y"};
d.put(k, 1);
System.out.println(d.get(k));
System.out.println(d.get(new String[]{"x", "y"}));
It outputs:
1
null
This means reference to String[]
is getting hashed instead of the value.
An inefficient way I can think of is concatenating elements from String[]
into a single String
.
Is there a better way?
Yes, a tuple is a hashable value and can be used as a dictionary key. A tuple would be useful as a key when storing values associated with a grid or some other coordinate type system. The following code example shows a dictionary with keys representing a simple x,y grid system.
HashMap stores key, value pairs and it does not allow duplicate keys. If the key is duplicate then the old key is replaced with the new value.
Tuples can be used as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable object either directly or indirectly, it cannot be used as a key.
If you try to insert the duplicate key, it will replace the element of the corresponding key. HashMap is similar to HashTable, but it is unsynchronized. It allows to store the null keys as well, but there should be only one null key object and there can be any number of null values.
HashMaps use Object.hashCode()
to create the hash. This, by default, uses a hash of the object that is unique for each instance - but doesn't look into any contents.
You migth want to create a tuple that overrides hashCode()
and, in addition to that, is immutable once created:
public class Tuple<T> {
private final T[] contents;
public Tuple (T[] contents) {
if (contents.length != 2)
throw new IllegalArgumentException();
this.contents = contents;
}
public T[] getContents () {
return this.contents.clone();
}
@Override
public int hashCode () {
return Arrays.deepHashCode(this.contents);
}
@Override
public boolean equals (Object other) {
return Arrays.deepEquals(this.contents, other.getContents());
}
@Override
public String toString () {
return Arrays.deepToString(this.contents);
}
}
[Edit]: Note that, if mutable objects are used instead of strings, the getter must perform a deep copy, not just a simple clone()
to ensure immutability.
Arrays in Java don't provide hashCode()
and equals(Object)
methods, so they aren't appropriate as map keys.
What you could use instead is Arrays.asList(string1, string1, etc)
which would give you an immutable List
, which all the methods needed for a Map
's key.
You could use Arrays.toString(myArray) as your key.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With