For the below code it outputs " 1 ". and second code outputs " 2 " I don't understand why this is happening. Is it because I am adding the same object? How should I achieve the desired output 2.
import java.util.*;
public class maptest {
public static void main(String[] args) {
Set<Integer[]> set = new HashSet<Integer[]>();
Integer[] t = new Integer[2];
t[0] = t[1] = 1;
set.add(t);
Integer[] t1 = new Integer[2];
t[0] = t[1] = 0;
set.add(t);
System.out.println(set.size());
}
}
Second Code:
import java.util.*;
public class maptest {
public static void main(String[] args) {
Set<Integer[]> set = new HashSet<Integer[]>();
Integer[] t = new Integer[2];
t[0] = t[1] = 1;
set.add(t);
Integer[] t1 = new Integer[2];
t1[0] = t1[1] = 1;
set.add(t1);
System.out.println(set.size());
}
}
The
Set
implementation probably callst.hashCode()
and since arrays don't override theObject.hashCode
method, the same object will have the same hashcode. Changing the array's contents thus does not affect its hash code. To get an array's hash code correctly, you should callArrays.hashCode
.You shouldn't really put mutable things inside sets anyways, so I would suggest you put immutable lists into sets instead. If you want to stick with arrays, just create a new array, like you did with
t1
, and put it into the set.EDIT:
For code 2,
t
andt1
are two different arrays so their hash code are different. Again, since thehashCode
method is not overridden in arrays. The array's contents don't effect the hash code, whether or not they are the same.How
java.util.Set
implementations check for duplicate objects depends on the implementation, but per the documentation ofSet
, the appropriate meaning of "duplicate" is thato1.equals(o2)
.Since
HashSet
in particular is based on a hash table, it will go about looking for a duplicate by computing thehashCode()
of the object presented to it, and then going through all the objects, if any, in the corresponding hash bucket.Arrays do not override
hashCode()
orequals()
, so they implement instance identity, not value identity. Thus, regardless of the values of its elements, a given array always has the same hash code, and alwaysequals()
itself and only itself. You first code adds the same array object to a set two times. Regardless of the values of its elements, it is still the same set. The second code adds two different array objects to a set. Regardless of the values of their elements, they are different objects.Note, too, that if you have mutable objects that implement value identity, such that their equality and hash codes depends on the values of their members, then modifying such an object while it is a member of a
Set
very likely breaks theSet
. This is documented on a per-implementation basis.You're adding the
Object
to aSet
whichYou are only ever adding one
Object
to theSet
. You only change the value of it's contents. To see what I mean try addingSystem.out.println(set.add(t));
.As the
add()
method:Also your
t1
is completely irrelevant in your first code snippet as you never use it.In your second code snippet it outputs two because you are adding two different
Integer[]
Objects
to theSet
Try printing out the hashcode of the
Objects
to see how this works:Output:
A
Set
contains only distinct element (it is its nature). The basic implementation,HashSet
, usehashCode()
to first find a bucket containing values thenequals(Object)
to look for a distinct value.Arrays are simple: their hashCode() use the default, inherited from
Object
, and therefore depending on reference. Theequals(Object)
is also the same thanObject
: it check only the identify, that is: references must be equals.Defined as Java:
If you want to put distinct arrays, you'll have to either try your luck with
TreeSet
and a proper implementation ofComparator
, either wrap you array or use aList
or anotherSet
:As for mutability of the object used in a
Set
or aMap
key:boolean equals(Object)
should not be muted because the muted object could be then equals to another. The Set would no longer contains distinct values.int hashCode()
should not be muted for hash based collection (HashSet
,HashMap
) because as said above their operate by putting items in a bucket. If the hashCode() change, it is likely the place of the object in the bucket will also change: theSet
would then contains twice the same reference.int compareTo(T)
orComparator::compare(T,T)
should not be muted for the same reason thanequals
: theSortedSet
would not know there was a change.If the need arise, you would have to first remove item from the set, then mutate it, the re-add it.