关于hashcode()与equals()方法的重写

学习地址:https://blog.csdn.net/wangyunpeng0319/article/details/74156934 

    1、我们为什么需要重写hashCode()方法和equals()方法
    
    首先equals() 与hashCode()方法是Java父类Object定义的方法;
    源代码中是如此定义的两个方法:
    public native int hashCode();
    public boolean equals(Object obj) {
        return (this == obj);
    }
    Java中的超类Object类中定义的equals()方法是用来比较两个引用所指向的对象的内存地址是否一致
    Object类中的hashCode()方法,用native关键字修饰,说明这个方法是个原生函数,也就说这个方法的实现不是用java语言实现的,是使用c/c++实现的,并且被编译成了DLL,由java去调用,jdk源码中不包含。对于不同的平台它们是不同的,java在不同的操作系统中调用不同的native方法实现对操作系统的访问,因为java语言不能直接访问操作系统底层,因为它没有指针。

    Java的API文档对hashCode()方法做了详细的说明,这也是我们重写hashCode()方法时的原则【Object类】

    重点要注意的是:

    a.  在java应用程序运行时,无论何时多次调用同一个对象时的hsahCode()方法,这个对象的hashCode()方法的返回值必须是相同的一个int值

    b.  如果两个对象equals()返回值为true,则他们的hashCode()也必须返回相同的int值

    c.  如果两个对象equals()返回值为false,则他们的hashCode()返回值也必须不同
    
    2、在什么情况下需要重写hashCode()方法和equals()方法
    
    我们在定义类时,我们经常会希望两个不同对象的某些属性值相同时就认为他们相同,所以我们要重写equals()方法,按照原则,我们重写了equals()方法,也要重写hashCode()方法,要保证上面所述的b,c原则;所以java中的很多类都重写了这两个方法,例如String类,包装类
    当我们自定义的一个类,想要把它的实例保存在集合中时,我们就需要重写这两个方法;
        如果使用自定义的类来作为TreeMap中的key值,且想让TreeMap能够良好的工作,则必须重写自定义类中的equals()方法,TreeMap中判断相等的标准是:两个key通过equals()方法返回为true,并且通过compareTo()方法比较应该返回为0。

        当向HashSet结合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置。简单的说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值也相等。
        注意,如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。其规则是如果两个对象通过equals方法比较返回true时,其hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值。
    
    
    3、如何重写这两个方法

         以集合类TreeMap为例:

package com.basic.util;
 
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.TreeMap;
 
public class BasicTreeMap {
	public static void main(String[] args) {
		Student s1 = new Student("lpn", 27, 61.38);
		Student s2 = new Student("tbn", 28, 62.211);
		Student s3 = new Student("xyz", 29, 63.345);
		Student s4 = new Student("qwe", 30, 64.986);
		
		TreeMap<Student, Integer> tMap = new TreeMap<Student, Integer>(new StudentCmp());
		tMap.put(s1, 1);
		tMap.put(s4, 4);
		tMap.put(s2, 2);
		tMap.put(s3, 3);
		tMap.put(s1, 100);
		tMap.put(s3, null);
		tMap.remove(s3);
		
		Iterator<Entry<Student, Integer>> iterr = tMap.entrySet().iterator();
		while (iterr.hasNext()) {
			Entry<Student, Integer> e = iterr.next();
			if (e.getKey().equals(s4)) {
				iterr.remove();
			}
		}
		
		/** Caused Exception java.util.ConcurrentModificationException
		for (Entry<Student, Integer> e : tMap.entrySet()) {
			if (e.getValue() == 2) {
				tMap.remove(e.getKey());
			}
		}
		*/
		
		Iterator<Entry<Student, Integer>> iter = tMap.entrySet().iterator();
		while (iter.hasNext()) {
			Entry<Student, Integer> e = iter.next();
			System.out.println(e.getKey().toString() + " " + e.getValue());
		}
		
		for (Entry<Student, Integer> e : tMap.entrySet()) {
			System.out.println(e.getKey().toString() + " " + e.getValue());
		}
	}
}
 
 
class Student implements Comparable<Student> {
	private String name;
	private int age;
	private double height;
	
	public Student() {
	}
	
	public Student(String name, int age, double height) {
		this.name = name;
		this.age = age;
		this.height = height;
	}
	
	
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
 
	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}
 
	/**
	 * @return the age
	 */
	public int getAge() {
		return age;
	}
 
	/**
	 * @param age the age to set
	 */
	public void setAge(int age) {
		this.age = age;
	}
 
	/**
	 * @return the height
	 */
	public double getHeight() {
		return height;
	}
 
	/**
	 * @param height the height to set
	 */
	public void setHeight(double height) {
		this.height = height;
	}
 
	@Override
	public int hashCode() {
		int result = 1;
		final int prime = 31;
		result = result*prime + name == null ? 0 : name.hashCode();
		result = result*prime + age;
		result = result*prime + (int) Double.doubleToLongBits(height);
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (null == obj) {
			return false;
		}
		if (!(obj instanceof Student)) {
			return false;
		}
		Student s = (Student) obj;
		if (name != null) {
			if (s.name == null || !name.equals(s.name)) {
				return false;
			}
		} else {
			if (s.name != null) {
				return false;
			}
		}
		if (age != s.age) {
			return false;
		}
		if (Double.doubleToLongBits(height) != Double.doubleToLongBits(s.height)) {
			return false;
		}
		return true;
	}
	
	@Override
	public String toString() {
		String str = "";
		str = name + " " + age + " " + height;
		return str;
	}
 
	@Override
	public int compareTo(Student o) {
		if (this.age < o.age) {
			return -1;
		} else if (this.age > o.age) {
			return 1;
		}
		return 0;
	}
}
 
class StudentCmp implements Comparator<Student> {
 
	@Override
	public int compare(Student o1, Student o2) {
		if (o2.getAge() < o1.getAge()) {
			return -1;
		} else if (o2.getAge() > o1.getAge()) {
			return 1;
		}
		return 0;
	}
	
}


最后某些特殊情况下,可能需要基于value排序,下面的代码实现了基于value排序,并考虑了value为null的情况

List<Entry<Student, Integer>> lEntry = new ArrayList<Entry<Student, Integer>>(tMap.entrySet());
		Collections.sort(lEntry, new Comparator<Entry<Student, Integer>> () {
			@Override
			public int compare(Entry<Student, Integer> o1, Entry<Student, Integer> o2) {
				if (o1.getValue() != null && o2.getValue() != null) {
					return o2.getValue() - o1.getValue();
				} else if (o1.getValue() == null) {
					return 1;
				} else {
					return -1;
				}
			}
		});
	

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: hashCodeequals是Java中Object类的两个方法。它们的重写是为了在自定义类中实现对象的比较和哈希码生成。 hashCode方法用于生成对象的哈希码,哈希码是一个整数,用于快速比较对象是否相等。在重写hashCode方法时,需要保证相等的对象生成相同的哈希码,不相等的对象生成不同的哈希码。 equals方法用于比较两个对象是否相等。在重写equals方法时,需要保证相等的对象返回true,不相等的对象返回false。通常需要重写hashCode方法equals方法一起使用,以确保对象的正确比较和哈希码生成。 ### 回答2: hashcodeequals是Java中Object类中的两个重要方法。在需要比较对象相等性和进行哈希表存储的场景中,我们常常需要重写这两个方法hashcode方法返回对象的哈希码,用于确定对象在哈希表中的位置。哈希码是根据对象的内部信息计算出来的整型数值。具有相等的对象必须具有相等的哈希码,但相等的哈希码不一定代表对象相等。在重写hashcode方法时,一般应该按照对象中的所有重要属性,如字符串、数值等进行哈希码的计算,保持一致性。同时,我们也需要遵循一些规则,如相等的对象必须具有相等的哈希码,避免哈希冲突。 equals方法用于比较对象的相等性。equals方法被定义为Object类的一个方法,其默认行为是比较对象的引用。因此,在我们自定义的类中,如果需要比较对象的内容,就需要重写equals方法。我们重写equals方法时,一般应该比较对象中的所有重要属性是否相等。并且,还需要保证equals方法满足一些规则,如自反性、对称性、传递性和一致性等。 在重写hashcodeequals方法时,需要保证hashcodeequals方法的一致性,即如果两个对象相等,则它们的哈希码也必须相等。这样可以保证相等的对象在哈希表中的位置一致。 总而言之,重写hashcodeequals方法是为了在需要比较对象相等性和进行哈希表存储的场景中能够正确判断对象的相等性。这两个方法的逻辑需要按照对象自身的特性进行实现,以确保正确性和一致性。 ### 回答3: hashCodeequals是Java中Object类中的两个方法。在开发中,有时需要重写这两个方法来实现自定义的对象比较和哈希值计算。 hashCode方法用于计算对象的哈希值,它返回一个对象的整型数值,用于在哈希表等数据结构中快速定位对象。Java中的哈希值计算方法是将对象的内存地址经过某种算法转换为整数。如果我们自定义的对象需要用于集合类(如HashSet、HashMap)等需要快速查找和比较的场合,就需要重写hashCode方法。在重写时,我们可以以对象的属性作为计算哈希值的依据,确保相等的对象具有相等的哈希值。 equals方法用于比较两个对象是否相等,默认情况下,equals比较的是对象的内存地址。但在实际开发中,我们可能需要定义两个对象相等的标准,比如两个用户对象的用户名相同即可认为相等。此时,我们就需要重写equals方法,根据自定义的标准来比较对象的属性。在重写时,必须满足以下几个条件: 1. 自反性:对于任意非空引用x,x.equals(x)必须返回true。 2. 对称性:对于任意非空引用x和y,如果x.equals(y)返回true,那么y.equals(x)也必须返回true。 3. 传递性:对于任意非空引用x、y和z,如果x.equals(y)返回true,y.equals(z)也返回true,那么x.equals(z)也必须返回true。 4. 一致性:对于任意非空引用x和y,如果x和y的属性没有发生变化,多次调用x.equals(y)应该返回相同的结果。 5. 对于任意非空引用x,x.equals(null)必须返回false。 hashCodeequals重写是为了让我们能够根据我们自定义的规则来比较和存储对象,并且保证在集合类中能够正常使用。使用IDE自动生成hashCodeequals方法可以确保满足上述的条件,减少了出错的可能性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值