简体   繁体   English

HashSet“包含”方法如何工作?

[英]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? 我使用Set:HashSet和TreeSet的2种实现。我添加了10个元素以通过set中的contains方法设置和查找对象。我看到contains方法会迭代所有对象,尽管它找到了element。出于性能原因,我感到困惑。为什么所以,我该如何预防呢?

I have a Person class: 我有一个Person类:

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: 在主类中,我添加10 Person对象,然后通过set的第一个元素调用contains方法:

    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. 您的equals()方法错误。 It returns true whatever the other person is. 无论其他人是什么,它都会返回true。

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. 它不遵守equals() ,BTW的约定,因为相等的对象应具有相等的hashCode,并且hashCode是人的ID。 So two persons with different IDs have a different hashCode, but are still equal. 因此,具有不同ID的两个人具有不同的hashCode,但仍然相等。

That said, your test shows that hashCode() is executed 10 times. 也就是说,您的测试显示hashCode()被执行10次。 But it's not executed by contains() . 但是它不是由contains()执行的。 It's executed by add() . 它由add()执行。 Every time you add an object to the set, its hashCode() is used to know which bucket should hold the object. 每次将对象添加到集合中时,都会使用其hashCode()来知道哪个存储桶应容纳该对象。

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. 前十个打印可能用于插入代码,后一个打印用于contains调用。 I hope that is the thing which might be confusing you. 我希望这可能会使您感到困惑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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