为什么对象不相同添加到具有相同值的hashset,甚至hashCode和equals都被覆盖

时间:2015-06-22 11:24:00

标签: java equals hashcode hashset

这是生成hashset大小3而不是2

的代码
package dump.test;
import java.util.*;
public class WrappedString {
    private String s;
    public WrappedString(String s) { this.s = s; }
    public static void main(String[] args) {
        HashSet<Object> hs = new HashSet<Object>();
        WrappedString ws1 = new WrappedString("aardvark");
        WrappedString ws2 = new WrappedString("aardvark");
        String s1 = new String("aardvark");
        String s2 = new String("aardvark");
        hs.add(ws1); hs.add(ws2); hs.add(s1); hs.add(s2);
        System.out.println(hs.size()+hs.toString()); 
    }
    public boolean equals(Object aSong) {
        String s = aSong.toString();
        System.out.println(s);
        return s.equals(this.s);
    }
    public int hashCode() {
        System.out.println(this.s + "-" + this.s.hashCode());
        return this.s.hashCode();
    }
    /*public int compareTo(Object aSong) {
        String s = aSong.toString();
        return this.s.compareTo(s);
    }*/
}

如果等于和hashCode被覆盖,它总是打印在输出下面 enter image description here

您可以看到两个对象在输出中具有相同的代码但计为不同,并将计数生成为3

这是因为我们不重写equals和hashCode enter image description here

请帮我解决这个问题。

3 个答案:

答案 0 :(得分:3)

问题在于您的案例不对称。如果实现决定在您的类作为参数的情况下调用equals实例上的String,它肯定会返回false,因此您的代码将无法始终工作。

答案 1 :(得分:2)

从Set接口的JavaDoc:

  

不包含重复元素的集合。更正式地说,集合不包含元素对e1和e2,使得e1.equals(e2)和至多一个null元素。正如其名称所暗示的,该界面模拟数学集抽象。

因此,HashSet在添加新元素之前检查equals(Object)。由于第二个String等于第一个,因此不会添加。在WrappedString上,您没有覆盖equals(Object),因此,您正在使用从Object继承的那个,它只检查对象ID(659e0bfd和{{1在你的情况下)。

答案 2 :(得分:0)

添加

public String toString() { return this.s; }

清除了我的困惑。以前它无法将铸造对象的真值转换为字符串,并且需要覆盖toString以返回基础值。