JAVA 为啥要重写equals 方法才能对一个值进行操作(容器)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA 为啥要重写equals 方法才能对一个值进行操作(容器)相关的知识,希望对你有一定的参考价值。

import java.util.*;

public class BasicContainer
public static void main(String[] args)
Collection c = new HashSet();
c.add("hello");
c.add(new Name("f1","l1"));
c.add(new Integer(100));

c.remove("hello");
c.remove(new Integer(100));
System.out.println
(c.remove(new Name("f1","l1"))); //如果我下面没重写Object的equals方法为什么不能修改Name的值??
System.out.println(c);




class Name /*implements Comparable*/

private String firstName,lastName;

public Name(String firstName, String lastName)
this.firstName = firstName;
this.lastName = lastName;


public String getFirstName()
return firstName;

public String getLastName()
return lastName;

public String toString()
return firstName + " " + lastName;


public boolean equals(Object obj)
if (obj instanceof Name)
Name name = (Name) obj;
return (firstName.equals(name.firstName))
&& (lastName.equals(name.lastName));

return super.equals(obj);

public int hashCode()
return firstName.hashCode();

c.remove() 方法是根据参数对象去容器里面查找相等的对象,进行删除操作。而相等的依据就是用equals方法和hashCode方法。如果你的Name类不重写equals方法,就会用Object的equals方法去比较。Object本身的hashCode()方法每new一个hashCode都不一样,所以在容器里找不到你要删除的对象(虽然值一样)。
所以你必须重写equals方法根据对象的属性值来判断两个对象是否相等。追问

public boolean equals(Object obj)

这里传进来的是哪个Name ?

c.add(new Name("f1","l1")); 这个 ? 还是

System.out.println
(c.remove(new Name("f1","l1"))); 这个 ?

基础不是很好

参考技术A 查API文档,它是这样说的The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true). 翻译过来意思就是:Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。
所以object的equal方法只有被重写之后才能比较这两个对象的“内容”是不是相同,而不是比较是不是同一个对象。显而易见,楼主的这段程序不重写Object方法比较的两者是不是同一个Name对象 当然就不能remove成功了。所以就有当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

我初学容器的时候也有同样的疑惑,建议楼主多查API文档,加油,祝你成功!追问

public boolean equals(Object obj)

这里传进来的是哪个Name ?

c.add(new Name("f1","l1")); 这个 ? 还是

System.out.println
(c.remove(new Name("f1","l1"))); 这个 ?

基础不是很好

追答

当然是调用remove方法时的了,因为你要移除c.add(new Name("f1","l1")) 这个生成的Name。所以你要调用equal比较再生成一个Name比较两个内容是否相同:c.remove(new Name("f1","l1"))); (这里的new Name是新生成的)

参考技术B 你说的什么意思??什么叫你能修改name值?建议你去看看object的equals方法:public boolean equals(Object obj),所有类都默认继承object类,也就是name类继承了object的equals方法,此equals方法内部不可能知道name类的firstName、lastName属性,更不可能去判断firstName、lastName属性是否正确了。追问

public boolean equals(Object obj)

这里传进来的是哪个Name ?

c.add(new Name("f1","l1")); 这个 ? 还是

System.out.println
(c.remove(new Name("f1","l1"))); 这个 ?

基础不是很好

追答

后面那个,在打印对象时默认调用equals方法

java 基础笔记--hashCode(),你好,为啥要重写

   从学习java开始就知道,hashCode()方法是object类本身就有的方法,所有的类都继承了object,也就了hashCode()这个方法。

在学java的时候,就被告知在重写equals方法时,也要重写hashCode方法。当时没细想,以为这个是语法规定。

  后来了解到,这个确实java规定:

  hashcode相等的两个对象内容不一定相等。

  对象内容相等的两个对象hashcode一定相等!

 

  如果比较两个对象是否相等。比较两个对象的内容涉及的东西比较多,但是hashcode只是一个int数字,要比较还是不简单!性能上比equals快多了。在set,map等集合类中,代码中都是先利用hashcode判断key是否存在和重复。这也就是如果自定义类作为key时,要求要重写hashCode方法。

默认的hashcode的值是对象在内存中的地址。

随便提一下,String也是重写了hashCode方法的。

String类关键代码如下:

/**
     * Returns a hash code for this string. The hash code for a
     * {@code String} object is computed as
     * <blockquote><pre>
     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
     * </pre></blockquote>
     * using {@code int} arithmetic, where {@code s[i]} is the
     * <i>i</i>th character of the string, {@code n} is the length of
     * the string, and {@code ^} indicates exponentiation.
     * (The hash value of the empty string is zero.)
     *
     * @return  a hash code value for this object.
     */
    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }
View Code

就是它了,根据内容来决定hashcode的值的。

测试代码如下:

public class Dog {
    private int age;
    private String name;
    public Dog(String name,int age){
        this.name=name;
        this.age=age;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    
}

 

public class Hash {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String a="abc";
        String b=new String("abc");
        String c=new String("abc");
        String d="abc";
        System.out.println(" a hashcode:"+a.hashCode()+"--"+(a==d));
        System.out.println(" b hashcode:"+b.hashCode()+"--"+(b==c));
        System.out.println("c hashcode:"+c.hashCode());
        System.out.println("d hashcode:" +d.hashCode());
        Dog dog1=new Dog("aa", 1);
        Dog dog2=new Dog("aa", 1);
        
        System.out.println(dog1.hashCode());
        System.out.println(dog2.hashCode());
        
    }

}

  运行结果(每次运行dog的hashcode的结果不一样。下图仅仅是参考):

至于equals的方法介绍参考

https://www.cnblogs.com/yxnchinahlj/archive/2010/09/27/1836556.html 

 

以上是关于JAVA 为啥要重写equals 方法才能对一个值进行操作(容器)的主要内容,如果未能解决你的问题,请参考以下文章

为啥重写equals方法,一定要重写HashCode方法?

【彻底理解】 为啥重写equals()方法为啥要重写hashCode()方法

java中重写Object类的equals方法为啥要重写hashcode方法?不重写可以吗?

java中重写Object类的equals方法为啥要重写hashcode方法?不重写可以吗?

JAVA中重写equals()方法为什么要重写hashcode()方法说明

java 基础笔记--hashCode(),你好,为啥要重写