Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing arrays in Set and avoiding duplicates

HashSet<String[]> boog = new HashSet<String[]>(); boog.add(new String[]{"a", "b", "c"}); boog.add(new String[]{"a", "b", "c"}); boog.add(new String[]{"a", "b", "d"}); 

results in

[a, b, c] [a, b, d] [a, b, c] 

where [a,b,c] is repeated, so the hash function is not working as expected. How would I go about overriding the Hash method for String arrays. Or for that matter, a generic array? Is there a better way to accomplish what I'm trying to do?

like image 284
Booker Avatar asked Sep 20 '11 15:09

Booker


People also ask

Can you store arrays in a Set?

You can't. arrays use the default identity-based Object.

How does Set ensure that there are no duplicates?

The meaning of "sets do not allow duplicate values" is that when you add a duplicate to a set, the duplicate is ignored, and the set remains unchanged. This does not lead to compile or runtime errors: duplicates are silently ignored.

Do arrays allow duplicates?

We know that HashSet doesn't allow duplicate values in it. We can make use of this property to check for duplicates in an array. The idea is to insert all array elements into a HashSet . Now the array contains a duplicate if the array's length is not equal to the set's size.


2 Answers

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.

like image 106
Sean Patrick Floyd Avatar answered Oct 05 '22 12:10

Sean Patrick Floyd


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 

Edit

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);    } }         
like image 38
Mark Peters Avatar answered Oct 05 '22 13:10

Mark Peters