String类中的Object&equals方法与自定义类中Object的相等方法有什么区别

时间:2014-12-28 22:50:02

标签: java

我无法理解String类中equals方法的行为(区别),然后在自定义类中手动覆盖equals方法。

根据java,如果我们想要两个对象相等,那么我们应该重写equals方法来检查它们之间的相等性。所以,我创建了一个Dog类并覆盖该类中的equals方法。进一步检查对象之间的相等性我使用Set类型集合,因为它不允许重复。但我很困惑看到输出。这是我的代码:

import java.util.*;

class Dog{
    int type;

    public int getType() {
        return type;
    }
    public void setType(int type) {
        this.type = type;
    }

    public boolean equals(Object o){
    if((o instanceof Dog) && ((Dog)o).getType()==this.getType()){
        return true;
    }
    else{
        return false;
    }
}
}
public class CheckEquality {
    public static void main(String[] args) {
        Dog d1=new Dog();
        Dog d2=new Dog();

        d1.setType(12);
        d2.setType(12);
        Set set=new HashSet();
        if(set.add(d1)){
            System.out.println("d1 added");
        }
        if(set.add(d2)){
            System.out.println("d2 added");
        }

        String s1=new String("ad");
        String s2=new String("ad");
        //String s1="ad";
        //String s2="ad";
        Set set2=new HashSet();
        if(set2.add(s1)){
            System.out.println("s1 added");
        }
        if(set2.add(s2)){
            System.out.println("s2 added");
        }

    }
}

输出:

d1 added
d2 added
s1 added

我的期望:

d1 added
s1 added

任何人都可以告诉我为什么我会收到d2 addedd语句,当可以看到同一个type的对象已添加到Set时。

相反,String不允许使用语句s2 added。为什么会这样?任何人都可以清除我的怀疑。

4 个答案:

答案 0 :(得分:3)

因为您还必须覆盖hashCode。检查Object#equals的合同:

  

请注意,通常需要在重写此方法时覆盖hashCode方法,以便维护hashCode方法的常规协定,该方法声明相等的对象必须具有相同的哈希代码。

将此添加到您的Dog课程:

public class Dog {
    @Override
    public int hashCode() {
        return this.type;
    }
}

这只是一个基本的例子。如果typefinal字段,那会更好。来自Object#hashCode

  

每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终返回相同的整数,前提是没有等于比较的信息对象被修改。从应用程序的一次执行到同一应用程序的另一次执行,此整数不需要保持一致。

答案 1 :(得分:2)

您缺少hashCode方法。

  

此哈希在存储或操作时由其他代码使用   实例 - 值旨在均匀分布以用于变化   输入以便在群集中使用。这个属性很重要   存储的哈希表和其他数据结构的性能   组中的对象("存储桶")基于其计算的哈希值

您可以使用Objects类生成哈希码。

public class Dog {
    @Override
    public int hashCode() {
        return Objects.hash(type);
    }
}

答案 2 :(得分:2)

Set - 实施HashSet应使用hashCode查找值。您的对象不提供良好的hashCode,而是使用Object中的版本。在实现equals时,通常也应该始终实现hashCode。它只是最佳实践

在Java 8中,您可以使用以下代码提供良好且高效的哈希:

Objects.hash(value1, value2, value3);

如果使用得当,HashSet将按预期工作。对于简单Dog - 类,可以返回type,但对于包含更多属性的更复杂对象,建议使用Objects.hash或类似。

答案 3 :(得分:0)

如果不重写哈希码方法,则在将对象存储在哈希集中时会出现冲突问题。哈希集内部使用哈希表来键和值对。

由于必须重写哈希码,以便哈希集找到相同的哈希码,因此它将在内部调用equals方法。

webView.getEngine().loadContent("<p>my text</p>");
webView.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
    if (newValue == Worker.State.SUCCEEDED)
        webView.getEngine().executeScript("window.scrollTo(0, document.body.scrollHeight);");
}