正确重写equals方法和compareTo方法

一、概述

程序要对一堆数据元素排序,查找,增加删除。
数据节点

class Node{
        int type;
        int index;
        int score;
}

  

规则:
  1)对象相等:两个节点n1与n2,如果n1.type == n2.type && n1.index == n2.index则n1等于n2
  2)排序:升序,比较score,score相同则比较type,type相同则比较index.
最开始我使用TreeMap存储。实现Comparable接口,重写equals方法与hashCode方法。
如下:

class Node implements Comparable<Node>{
	public int type;
	public int index;
	public int score;
	public Node(int t, int u, int s) {
		this.type = t;
		this.index = u;
		this.score = s;
	}
	@Override
	public int compareTo(Node o) {
		if(this.score != o.score) return this.score > o.score ? -1 : 1;
		else if(this.type != o.type) return this.type - o.type;
		else return this.index - o.index;
	}
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(this == obj) return true;
		if(obj instanceof Node) {
			Node tn = (Node) obj;
			if(tn.type == this.type && tn.index == this.index) return true;
		}
		return false;
	}
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return this.type + this.index;
	}
}

程序一直不对,经过两个小时反复的检查。我意识到,TreeMap比较对象是否相同也是调用CompareTo方法。equals和hashCode是HashMap那一套。
修改后,每个type的数据用一个TreeMap保存。
如下:

class Node implements Comparable<Node>{
	public int type;
	public int index;
	public int score;
	public Node(int t, int u, int s) {
		this.type = t;
		this.index = u;
		this.score = s;
	}
	@Override
	public int compareTo(Node o) {
		if(this.type == o.type && this.index == o.index) return 0;
		else {
			if(this.score != o.score) return this.score > o.score ? -1 : 1;
			else return this.index - o.index;
		}
	}
}

最后的排序使用优先队列。
比较器:

Comparetor<Node> cmp = (x, y) ->{
	if(x.score != y.score) return x.score > y.score ? -1: 1;
	else if(x.type != y.type) return x.type - y.type;
	return x.index - y.index;
}

正确使用equals和compareTo,减少bug。

二、重写equals

HashSet中存储自己定义的对象,HashMap使用自定义的对象作Key,都需要重写equals。同时要重写hashCode.
hashCode定位,equals比较对象是否相同。
如下:

@Override
public boolean equals(Object obj) {//参数类型必须为Object,否则无效
	// TODO Auto-generated method stub
	if(this == obj) return true; //同引用
	if(obj instanceof Node) {//obj为null时,条件为假。
		Node tn = (Node) obj;
		if(tn.type == this.type && tn.index == this.index) return true;//根据内容比较对象
	}
	return false;
}

hashCode方法要保证相同对象的返回值相同。想实现一个好的hashCode比较难。

三、重写compareTo

有序的集合,存储自定以的对象都需要重写compareTo方法或者提供该对象的比较器。常用到的集合有TreeMap(红黑树)、TreeSet、PriorityQueue(堆)、Arrays::sort(数组排序)、Collections::sort(List排序)。
如下:

class Data implements Comparable<Data>{ //实现Comparable接口
	@Override
	public int compareTo(Data o) {//小于返回负值,等于返回0,大于返回正值
		// TODO Auto-generated method stub
		return 0;
	}
}

比较器,如下:

Comparator<Node> cmp = new Comparator<Node>() {
		@Override
		public int compare(Node o1, Node o2) {
			// TODO Auto-generated method stub
			return 0;
		}
	};

使用Lambda表达式。

Comparetor<Node> cmp = (x, y) ->{
	if(x.score != y.score) return x.score > y.score ? -1: 1;
	else if(x.type != y.type) return x.type - y.type;
	return x.index - y.index;
}

原文地址:https://www.cnblogs.com/suen061/p/11524959.html

时间: 2024-11-10 21:59:10

正确重写equals方法和compareTo方法的相关文章

HashSet中存方用户自定义数据类型数据,重写equals方法和hashCode方法

import java.util.Set; import java.util.HashSet; public class SetTest { public static void main(String[] args) { /* *对于用户自定义类型的数据放在容器(Set)中 *务必重写equals和hashCode方法 *要不然stu1和stu2放在容器中,和认为是两个不同的元素 **/ //set中存放的元素是无序的 //set中存储的元素是不可以重复的(根据equals方法和hashCod

JAVA正确地自定义比较对象---如何重写equals方法和hashCode方法

在实际应用中经常会比较两个对象是否相等,比如下面的Address类,它有两个属性:String province 和 String city. public class Address { private String province; private String city; public String getProvince() { return province; } public void setProvince(String province) { this.province = p

重写equals()方法和 hashCode()方法

java中判断两个对象是否相等的规则:首先,判断两个对象的hashCode是否相等 如果不相等,认为两个对象也不相等 如果相等,则判断两个对象用equals运算是否相等 如果不相等,认为两个对象也不相等 如果相等,认为两个对象相等 我们在equals方法中需要向下转型,效率很低,所以先判断hashCode方法可以提高效率. equals()相等的两个对象,hashcode()一定相等: equals()不相等的两个对象,却并不能证明他们的hashcode()不相等. 1,所有Java类都继承自O

Java重写equals方法和hashCode方法

package com.ddy; public class User {     private Integer id; private String name; private String address; private String phone; public Integer getId() {         return id;     } public void setId(Integer id) {         this.id = id;     } public Strin

关于Object类的equals方法和hashCode方法

关于Object类的equals的特点,对于非空引用: 1.自反性:x.equals(x) return true : 2.对称性:x.equals(y)为true,那么y.equals(x)也为true: 3.传递性:x.equals(y)为true,y.equals(z)为true,那么x.equals(z)也为true: 4.一致性:x.equals(y)的第一次调用为true,那么x.equals(y)的第二次,第三次,...,第n次调用也为true,前提条件是在比较之间没有修改x,也没

详解equals()方法和hashCode()方法

前言 Java的基类Object提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希码.equals()和hashCode()都不是final方法,都可以被重写(overwrite). 本文介绍了2种方法在使用和重写时,一些需要注意的问题. 一.equal()方法 Object类中equals()方法实现如下: public boolean equals(Object obj) { return (this == obj); } 通过该实现

Java compare方法和compareTo方法

Java Comparator接口排序用法,详细介绍可以阅读这个链接的内容:https://www.cnblogs.com/shizhijie/p/7657049.html 对于 public int compare(Object arg0, Object arg1)的理解 1 //数组排序 2 String[] str = new String[5]; 3 Arrays.sort(str, new Comparator<String>() { 4 @Override 5 public int

String 类型equals方法和int == 方法效率比较

最近写了一个递归方法,在进行比较判断的时候,因为都是integer类型,而integer类型在大于127或者小于-128时会在新建一个,这是因为integer类型的拆装箱机制, 之前没有考虑过equals方法和 == 方法的效率,又为了避免integer类型的拆装箱机制导致的错误,所以将integer类型使用String.valueOf()方法,将所有的integer类型转为了字符串使用equals方法进行比较. 后来被我师傅不经意间看到,指出来这个错误,我立马改为了Integer.intVal

java为什么要重写hashCode方法和equals方法?

之前发布过一篇文章说的是关于 equals方法重写 http://www.cnblogs.com/aL0n4k/p/4777333.html 下面就hashCode方法发表一下本人的理解,仅供参考,交流. 在 关于java重写equals方法 已经提及说,比较2个对象的时候,要比较他们各自的属性. 那么重写hashCode方法是因为我们在接触到集合的时候,里面有个Set接口,他只能添加无序以及不重复的对象元素. 那有人会问,既然是这样我们直接用equals判断不就完了么? 实际上对Set集合而言