Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Hashset.contains() produces mysterious result

I don't usually code in Java, but recently I started not having a choice. I might have some major misunderstanding of how to properly use HashSet. So it might be possible something I did is just plain wrong. However I'm grateful for any help, you might offer. So the actual problem:

In a small program I was writing, I was generating very similar objects, which, when created, would have a very specific id (a string or in my last iteration a long). Because each object would spawn new objects, I wanted to filter out all those I already created. So I started throwing the id of every new object into my Hash(Set) and testing with HashSet.contains(), if an object was created before. Here is the complete code:

// hashtest.java
import java.util.HashSet;

class L {
    public long l;
    public L(long l) {
        this.l = l;
    }
    public int hashCode() {
        return (int)this.l;
    }
    public boolean equals(L other) {
        return (int)this.l == (int)other.l;
    }
}

class hashtest {
    public static void main(String args[]) {
        HashSet<L> hash = new HashSet<L>();
        L a = new L(2);
        L b = new L(2);
        hash.add(a);
        System.out.println(hash.contains(a));
        System.out.println(hash.contains(b));
        System.out.println(a.equals(b));
        System.out.println(a.hashCode() == b.hashCode());
    }
}

produces following output:

true
false
true
true    

so apparently, contains does not use the equals function provided by L, or I have some major misunderstanding of the concept ...

I tested it with openjdk (current version included in ubuntu) and the official current java from Oracle on Win7

for completeness official java-api documentation for HashSet.contains():

public boolean contains(Object o)

Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).

http://download.oracle.com/javase/6/docs/api/java/util/HashSet.html#contains(java.lang.Object)

Any ideas or suggestions?

like image 358
Jochen Avatar asked Nov 07 '10 00:11

Jochen


People also ask

How does HashSet contains method work?

The purpose of the contains method is to check if an element is present in a given HashSet. It returns true if the element is found, otherwise false. Whenever an object is passed to this method, the hash value gets calculated. Then, the corresponding bucket location gets resolved and traversed.

What HashSet contains in Java?

HashSet. contains() method is used to check whether a specific element is present in the HashSet or not. So basically it is used to check if a Set contains any particular element. Syntax: Hash_Set.contains(Object element) Parameters: The parameter element is of the type of HashSet.

How do I know if a HashSet contains?

The contains() method of Java HashSet class is used to check if this HashSet contains the specified element or not. It returns true if element is found otherwise, returns false.

Why HashSet has no get method?

HashSet does not have any method to retrieve the object from the HashSet. There is only a way to get objects from the HashSet via Iterator. When we create an object of HashSet, it internally creates an instance of HashMap with default initial capacity 16.


1 Answers

Your equals method needs to take an Object.
Because you declared it as taking an L, it becomes an additional overload instead of overriding the method.
Therefore, when the hashSet class calls equals, it resolves to the base Object.equals method. When you call equals, you call your overload because a and b are both declared as L instead of Object.

To prevent this issue in the future, you should add @Override whenever you override a method.
This way, the compiler will warn you if it isn't actually an override.

like image 111
SLaks Avatar answered Oct 24 '22 14:10

SLaks