我无法理解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
。为什么会这样?任何人都可以清除我的怀疑。
答案 0 :(得分:3)
因为您还必须覆盖hashCode
。检查Object#equals
的合同:
请注意,通常需要在重写此方法时覆盖hashCode方法,以便维护hashCode方法的常规协定,该方法声明相等的对象必须具有相同的哈希代码。
将此添加到您的Dog
课程:
public class Dog {
@Override
public int hashCode() {
return this.type;
}
}
这只是一个基本的例子。如果type
是final
字段,那会更好。来自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);");
}