以下两种情况的结果为何不同?

时间:2019-07-05 09:35:47

标签: java set equals

Set<String> set2 = new HashSet<>();
String s2 = new String("rajkumar");
String s3 = new String("rajkumar");

set2.add(s3);
set2.add(s2);
System.out.println(set2.size()); //this will output 1


Person p1= new Person("rajkumar", 25);
Person p2= new Person("rajkumar", 25);
Set<Person>set= new HashSet<>();

set.add(p1);
set.add(p2);
System.out.println(set.size());//This will output 2

为什么会这样。字符串对象的has哈希码不是应该不同吗?

这里的人班就像

public class Person {
    private String name;
    private int age;

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

5 个答案:

答案 0 :(得分:2)

Set允许唯一的条目。唯一性通过equals方法检查。 s2和s3都具有相同的文本,因此两者相等。字符串类实现equals方法进行文本比较。在将s3添加到现有集合时,不会添加s3对象,相反,该方法返回false,表示具有相同值的对象已经存在。

另一方面,Person类未实现equals和hashcode,因此将对引用进行比较。在这种情况下,两个对象都添加到集合中

浏览javadoc以获得更多信息。

答案 1 :(得分:1)

在Java中有字符串池,该池将相等的字符串保存在同一内存中。查看此链接:https://www.journaldev.com/797/what-is-java-string-pool。 如果要一次在集合中使用同一个人,则必须重写equals方法。

答案 2 :(得分:1)

  

Java Set接口java.util.Set表示对象的集合,其中Set中的每个对象都是唯一的。换句话说,在Java集中,同一对象不能出现多次。   source

哈希集由哈希图支持

set2的类型为String。 s2和s3都被视为相同的字符串,因此set2中仅存在一个条目

set接受类型为Person的对象,而p1和p2是不同的对象,尽管它们具有相同的字段。

要对此进行测试,请进一步更改s2或s3的字符串值,并尝试在Person类中创建equals和hashcode方法:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age &&
            Objects.equals(name, person.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

答案 3 :(得分:0)

查看HashSet的add方法实现

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
    }

它在内部使用Hashmap添加元素 现在看一下HashMap的内部实现

public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

您可以看到它调用了键的equals方法,即要在HashSet中添加的元素 字符串类具有等于任何自定义/用户定义类的默认实现,如果添加到集合中则必须覆盖等于和哈希码

答案 4 :(得分:0)

您可以看一下这篇文章:Can a set have duplicate elements?。这里很好地说明了set的工作方式。 但是,如果我们看您的问题,您的两个Strings都是相同的(equals比较)。另一方面,Person object不相同。如果您希望Person objectsString一样工作,则应该在class中使用overide equals method