正确重写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;
}
正确重写equals方法和compareTo方法的更多相关文章
- HashSet中存方用户自己定义数据类型数据,重写equals方法和hashCode方法
import java.util.Set; import java.util.HashSet; public class SetTest { public static void main(Strin ...
- JAVA正确地自定义比较对象---如何重写equals方法和hashCode方法
在实际应用中经常会比较两个对象是否相等,比如下面的Address类,它有两个属性:String province 和 String city. public class Address { priva ...
- Hibernate中为什么要重写equals方法和hashcode方法
1.*为什么要重写equals方法,首先我们来看一下equals源码: public boolean equals(Object anObject) { if (this == anObject) { ...
- 对象作为 map 的 key 时,需要重写 equals 方法和 hashCode 方法
对象作为 map 的 key 时,需要重写 hashCode 和 equals方法 如果没有重写 hashCode 方法,那么下面的代码示例会输出 null 我们首先定义一个对象:BmapPoint, ...
- Java重写equals方法和hashCode方法
package com.ddy; public class User { private Integer id; private String name; private St ...
- HashSet中的元素必须重写equals方法和hashCode方法
http://jingyan.baidu.com/article/d5a880eb8fb61d13f147cc99.html 1.为什么必须重写这两个方法. 2.什么事hashSet去重,符合什么样的 ...
- 关于Object类的equals方法和hashCode方法
关于Object类的equals的特点,对于非空引用: 1.自反性:x.equals(x) return true : 2.对称性:x.equals(y)为true,那么y.equals(x)也为tr ...
- Java 如何重写对象的 equals 方法和 hashCode 方法
前言:Java 对象如果要比较是否相等,则需要重写 equals 方法,同时重写 hashCode 方法,而且 hashCode 方法里面使用质数 31.接下来看看各种为什么. 一.需求: 对比两个对 ...
- 详解equals()方法和hashCode()方法
前言 Java的基类Object提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希码.equals()和hashCode()都不是final方 ...
随机推荐
- exe4j打包--exe转安装包
前面一篇已经详细的说明了打包成exe的步骤了,下面谈谈exe如何压缩成安装文件.这里用到之前的另外一个软件,具体软件看这篇文章 exe4j打包成exe 打开inno 编辑器 打开软件后我们选择 用[脚 ...
- 如何调教你的博客Episode2——移动端支持和UI美化
这个系列的文章是我在搭建博客园博客时所经历的过程. 在上一期如何调教你的博客Episode1——修改整体样式中,我们通过添加CSS样式,修改了页面的总体布局.但将文章发出之后,博客的布局就出现问题了: ...
- python(自用手册)三
第三章 基础 3.1编码初识 ascii 256字母没有中文 一个字节 8位 gbk 中国 中文2字节 16位 英文1字节8位 unicode 万国码 前期 2字节 8位 后期变成4个字节 32位 u ...
- Sublime Text 3 使用手册
Ctrl+Shift+P:打开命令面板 Ctrl+P:搜索项目中的文件 Ctrl+G:跳转到第几行 Ctrl+W:关闭当前打开文件 Ctrl+Shift+W:关闭所有打开文件 Ctrl+Shift+V ...
- (转)2019年给Java编程初学者的建议(附学习大纲)
本文链接:https://blog.csdn.net/javajlb/article/details/85920904 1. 引言这是一篇初学者干货,请耐心看完,希望对你有帮助 作为初学者的你,命中了 ...
- MonkeyRunner 第一天
1.安装集成Android SDK的环境(如Eclipse),主要是为了android的模拟器,安装python编译环境,MonkeyRunner是基于Jython 2.使用Eclipse打开Andr ...
- 危险的Hystrix线程池
本文介绍Hystrix线程池的工作原理和参数配置,指出存在的问题并提供规避方案,阅读本文需要对Hystrix有一定的了解. 文本讨论的内容,基于hystrix 1.5.18: <dependen ...
- 利用QGIS下载地图数据
这段时间做了一些利用地理信息进行定位导航的系列工作,其中很重要的一部分是如何获取到地图数据,比如道路的矢量图.某一区域的栅格图,我用到的主要工具是QGIS.QGIS是一个跨平台的免费应用,其中集成了对 ...
- jar在linux上运行
打jar后一直在linux远程的运行: nohup java -jar xxx.jar & CRT(打开时运行):(另外上传文件可使用“rz”命令,上传jar包) java -jar xxx. ...
- Python|队列Queue
一 前言 本文算是一次队列的学习笔记,Queue 模块实现了三种类型的队列,它们的区别仅仅是队列中元素被取回的顺序.在 FIFO 队列中,先添加的任务先取回.在 LIFO 队列中,最近被添加的元素先取 ...