简体   繁体   中英

How does HashSet “contains” method work?

i use 2 implementations of Set:HashSet and TreeSet.I added 10 elements to set and find object by contains method from set.I see that contains method iterate all of the objects although it found element.For performance reason i confused.Why it is so and how can i prevent it?

I have a Person class:

public class Person implements Comparable<Person>{

private int id;
private String name;

public Person() {
}

public Person(int id, String name) {
    this.id = id;
    this.name = name;
}


//getter and setters

@Override
public int hashCode() {
    System.out.println("hashcode:" + toString());
    return this.id;
}

@Override
public boolean equals(Object obj) {
    System.out.println("equals:" + toString());
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    final Person other = (Person) obj;
    return true;
}

@Override
public String toString() {
    return "Person{" + "id=" + id + ", name=" + name + '}';
}

@Override
public int compareTo(Person o) {
    System.out.println("compare to:"+getId()+" "+o.getId());
    if(o.getId() == getId()){
        return 0;
    }else if(o.getId()>getId()){
        return -1;
    }else {
        return 1;
    }
}

}

And in main class i add 10 Person object and then call contains method by first element of set:

    import beans.Person;
    import java.util.Date;
    import java.util.HashSet;
    import java.util.Set;

    public class Main {
        public static void main(String[] args) {
            Set<Person> people = new HashSet<>();
            for (int i = 0; i < 10; i++) {
                people.add(new Person(i, String.valueOf(i)));
            }

            Person find = people.iterator().next();
            if (people.contains(find)) {
                System.out.println("here"+find.getName());
            } 
        }
    }

And result:

hashcode:Person{id=0, name=0} <--here element has been found but it continues
hashcode:Person{id=1, name=1}
hashcode:Person{id=2, name=2}
hashcode:Person{id=3, name=3}
hashcode:Person{id=4, name=4}
hashcode:Person{id=5, name=5}
hashcode:Person{id=6, name=6}
hashcode:Person{id=7, name=7}
hashcode:Person{id=8, name=8}
hashcode:Person{id=9, name=9}
hashcode:Person{id=0, name=0}<-- second check
here:0

Your equals() method is wrong. It returns true whatever the other person is.

It doesn't respect the contract of equals() , BTW, since equal objects should have an equal hashCode, and the hashCode is the ID of the person. So two persons with different IDs have a different hashCode, but are still equal.

That said, your test shows that hashCode() is executed 10 times. But it's not executed by contains() . It's executed by add() . Every time you add an object to the set, its hashCode() is used to know which bucket should hold the object.

It doesn't iterate though all elements. The reason the hashcode is bring printed for each object is because the hashcode needs to be calculated when Inserting into the set.

The first 10 prints are perhaps for the insert code and last one for the contains call. I hope that is the thing which might be confusing you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM