HashSet boog = new HashSet();
boog.add(new String[]{\"a\", \"b\", \"c\"});
boog.add(new String[]{\"a\", \"b\", \"c\"});
boog.add(new
The "better way" is to use collections. Use a List
instead of a String[]
:
Set<List<String>> boog = //...
boog.add(Arrays.asList("a", "b", "c"));
boog.add(Arrays.asList("a", "b", "c"));
boog.add(Arrays.asList("a", "b", "d"));
System.out.println(boog.size()); // 2
If you absolutely needed to use arrays as keys, you could build a transparent wrapper around each key and put that in the map. Some libraries help you with that. For example, here's how you could do a Set<String[]>
using Trove:
Set<String[]> boog = new TCustomHashSet<String[]>(new ArrayHashingStrategy());
boog.add(new String[]{"a", "b", "c"});
boog.add(new String[]{"a", "b", "c"});
boog.add(new String[]{"a", "b", "d"});
System.out.println(boog.size()); // 2
//...
public class ArrayHashingStrategy extends HashingStrategy<Object[]> {
public int computeHashCode(Object[] array) {
return Arrays.hashCode(array);
}
public boolean equals(Object[] arr1, Object[] arr2) {
return Arrays.equals(arr1, arr2);
}
}
You can't. arrays use the default identity-based Object.hashCode() implementation and there's no way you can override that. Don't use Arrays as keys in a HashMap / HashSet!
Use a Set of Lists instead.
Actually, you can. You can use TreeSet
with provided Comparator
.
In your case it will be something like:
Set<String[]> boog = new TreeSet<>((o1, o2) -> {
for (int i = 0; i < o1.length; i++){
int cmp = o1[i].compareTo(o2[i]);
if (cmp != 0) {
return cmp;
}
}
return o1.length - o2.length;
});
Under the hood it will looks like alphabetic sorted tree.
You are actually using the default hashCode
method returning different values for all your different arrays!
The best way to solve this is either to use a Collection
(such as a List
or a Set
) or to define your own wrapper class such as:
public class StringArray {
public String[] stringArray;
[...] // constructors and methods
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
for(String string : stringArray){
result = prime * result + ((string == null) ? 0 : string.hashCode());
}
}
}
This class actually uses pretty much the same hashCode
method as the one for the List
.
You now handle:
HashSet<StringArray> boog = new HashSet<StringArray>();
hashCode()
of arrays uses the default implementation, which doesn't take into account the elements, and you can't change that.
You can use a List
instead, with a hashCode()
calculated based on the hashcodes of its elements. ArrayList
(as most implementations) uses such function.
Alternatively (but less preferable, unless you are forced somehow to use arrays), you can use a 'special' HashSet
where instead of invoking key.hashCode()
invoke Arrays.hashCode(array)
. To implement that extend HashMap
and then use Collections.newSetFromMap(map)