HashSet allows duplication

I cannot get the HashSet instance to work as expected. The code I use is as follows:

 import testing.Subclass; import java.util.HashSet; public class tester { public static void main(String[] args) throws Exception { HashSet<Subclass> set = new HashSet<Subclass>(); set.add(new Subclass("007812")); set.add(new Subclass("007813")); System.out.println("Set size " + set.size()); set.add(new Subclass("007812")); System.out.println("Set size " + set.size()); for(Subclass sub : set) { System.out.println(" sub acctNbr " + sub.getAcctNbr()); } } } 

Subclass

 public class Subclass implements Comparable<Subclass> { public Subclass(String acctNbr) { this.acctNbr = acctNbr; } private String acctNbr; public String getAcctNbr() { return this.acctNbr; } public int compareTo(Subclass other) { return this.getAcctNbr().compareTo(other.getAcctNbr()); } public boolean equals(Subclass other) { if(other.getAcctNbr().equals(this.getAcctNbr())) return true; else return false; } public int hashCode() { return acctNbr.hashCode(); } } 

This code outputs

 sross@sross-workstation:~/Documents$ javac testing/Subclass.java sross@sross-workstation:~/Documents$ javac tester.java sross@sross-workstation:~/Documents$ java tester Set size 2 Set size 3 sub acctNbr 007812 sub acctNbr 007812 sub acctNbr 007813 sross@sross-workstation:~/Documents$ 
+7
java duplicates hashset
source share
6 answers

You need to override equals(Object) . Instead, you implemented the equals method with the signature equals(Subclass) . Therefore, your HashSet uses the default equals(Object) method defined for Object to test equality.

The default implementation of equals(Object) based on the identity of the object, and therefore the set "allows" you to add two String , which, although semantically equal, are not the same object.

+20
source share

You did not redefine Object.equals() correctly.

 @Override public boolean equals(Object other) { if ((other == null) || !(other instanceof Subclass)) { return false; } return ((Sublcass) other).getAcctNbr().equals(this.getAcctNbr()); } 

The boolean equals(Subclass other) method creates a second method that you are not going to do.

+5
source share

Two meta points:

First, get used to using @Override every time you think you are overriding a method. This would result in your sample code not compiling, leading you to detect a problem.

Secondly, if you use the IDE, and it does not give you a nice bold warning, this is incorrectly configured! You have to fix it!

And if you are not using an IDE, you really should be. Once you have typed public boolean equals(Subclass other) , the text will change color and a warning message will appear telling you what your probable problem is.

By the way, the standard idiom for equals() that I converged with is this:

 @Override public boolean equals(Object object) { if (object instanceof Subclass) { Subclass that = (Subclass) object; return this.anInt == that.anInt && this.aString.equals(that.aString); // for example } return false; } 

In some cases, it is worth adding if (object == this) { return true; } if (object == this) { return true; } , but you really should not get used to it.

+3
source share

I had almost the same problem as everyone said you need to override the correct public boolean equals(Object o) method. But this is not enough!

It is also necessary to redefine public int hashCode() (like you), otherwise java will not call the equals method at all.

+1
source share

First, suppose your equals(Subclass other) must be equals(Object other) to override the java.lang.Object.equals() method as you want. The set probably calls the base implementation of equals() .

0
source share

Your equals method is never called. The equals signature requires an Object , not some other class (including any class that implements equals ).

 public boolean equals(Object other) { ... } 
0
source share

All Articles