Java 比较(==, equals, compareTo, compare)
在Java中,有 ==, equals(), compareTo(), compare() 等方法可以比较两个值或对象,比较容易混淆。画了个简单的思维导图总结一下

Java Compares
我经常记不住Java中的各种比较方法,为什么设计者要弄出这么多种比较?
设计源于生活,如果我们先想一想现实世界中一般会如何做比较,也许会对理解Java的设计有所帮助吧。那么,在现实世界中,我们是怎么进行比较的呢?
假如给定两个物体,如果要对二者作比较的话,一般我们会先问:
有可比性吗?
如果没有可比性,那就无需再谈。但是从广义上讲,其实任何东西都可以互相比较的,所以可比性是有个限定范围的,即如果要两者可比,那就得限定规则范围,这样也就可以理解 Java 中 compareTo 了:
**在 Java 中 compareTo() 可以比较的两个对象的类必须都实现 Comparable 接口。
compare() 则是 Comparator 接口定义的方法。**
如果有可比性,又会问:
为什么比?
比啥?
怎么比?
让我们挨个来看:
为什么比?
因为要根据比较的结果来做决策或决定,具体就不展开了,各种应用情况不一样。比如:公司的绩效考核评优,运动会比赛夺冠等等。
**在 Java 中 equals()的比较结果是 boolean 类型,如果是 true 则表示二者相同的时候do something, 否则不同的时候 do else things,
而compareTo() ,compare() 的比较结果是:0表示相同,正负数表示不同,至于是正负多少,看所不同的字符在编码表中的差距。至于为啥要这么设计,我初步的想法是,根据不同的返回值的大小,可以用于排序,但具体还没想通(以后补上)
比啥?
这个要比的方面真是很多,让我们简单举几个例子:
1。小朋友开始学数学的时候,会被问到“2”和“3”哪个大啊? 这里比较的是简单的数值,在Java中多设计为基本数据类型。
在 Java 中,用 == 来比较基本数据类型(Primitive Type),直接比较的是值(Value)是否相等。
equals() 和 compareTo() 都是方法,不适用于基本数据类型。
2。你一定听过也许是亲自体会过,“你看人家老王家的某某,这次又比你考的好。。。”,这比的啥?成绩,很直观的数据比较。类似还有,你和你弟弟一般高吗?量下身高数据即可。
这里也是数值,和前面的例子稍不同的是,身高是老王家的某某的一个指标,在 Java 中一般把老王家的某某,定义为某个类比如Person类的一个对象,身高则是他的一个属性。因为对象的属性通常比较多,为了简化问题,在这里让我们做个假设:两个对象是同一个类的对象,只有一个属性。这种情况下如何判断这两个对象是否相同呢?(比如是不是同一个人(Person)?)
在 Java 中,对于引用类型的对象,可以用重写Object类的equals()方法比较两个对象的属性值,也是看值(Value)是否相等。compareTo()似乎也可以用,不过应该不太常用在这种情况
3。你老板这天过来找你:小王,你比较下两个品牌电脑上半年的销售情况,我发了两个电子清单给你,下班前给我个报告。“ 这会儿不太好直接进行数据比较了,咋办?你准备写了Java程序来干这活,不然你今晚就得加班了。
这种情况在 Java 中,这两份文档就得作为引用类型来比较了,equals(), compareTo(),compare() 就派上用场了。== 也可以用,但一般不直接使用,容易出问题。
怎么比
写程序前,你先大概浏览了一下两个文件,突然发现怎么内容都差不多嘛,再仔细看看,分明就是同一份清单,可能老板复制了同一份。
在 Java 中,equals() 和 compareTo(), 包括compare()的实现, 在比较两个对象的时候,都会先做一个判断,判断二者是否是同一对象。这里就用到了 == ,比较的是这两个引用存的是否是同一地址
public boolean equals (Object x){
if(this == x) return true;
....
}
可能还有一种情况,你发现,咦,怎么有一份文件是空的?这没法比了。
在 Java 中,equals()方法 x.equals(null) 返回的是false。 而 x.compareTo(null) 返回的则是NullPointerException,这个得注意了。
不管怎样,后来终于可以认真比较了,你可能要比较很多方面:
- 各电脑品牌的销售地域是否相同
- 各地域销量是否相同
- 如何按价格排序
- 如何按销量排序
- ...
那么你是要用 equals(), 还是compareTo(), 亦或是compare()?
我个人的理解:
1。如果只是需要在某个方法中简单的比较属性值是否相等,用equals()
在 Java 中,equals() 是 Object 类的方法,有默认实现方法,返回值是boolean。(比如比较 两个String,如果长度不等,返回false, 否则比较各个字符,如均同则返回true)。
实际应用中,比如Date对象,Java默认的实现方式是比较getTime()毫秒级的,如果你的程序需要比较年月日,这时候可重写equals方法。
public boolean equals(Object x){
if (this == x) return true;
if (x == null) return false;
if (this.getClass() != x.getClass()) return false; // Not sure what if inheritance?
Date that = (Date) x;
if (this.day !=that.day) return false;
if(this.month!=that.month) return false;
if (this.year!=that.year) return false;
return true;
}
2。如果需要进行排序,可结合compareTo() 和 compare() 方法。
> compareTo(): 对象须实现 Comparable 接口 (必须有可比性)
> compare() : Comparator 接口中定义的方法,具体实现时可调用compareTo() 方法。
二者返回值类似,0 表示相同,负数表示排在前,正数表示排在后。
都是排序,有什么特别的区别吗?
> compareTo(): Java 称之为Lexicographically 排序,以String对象为例,从源码可看到,比较的是某一index上的字符的Unicode编码值。
- 每个index上的字符都相同且字符串长度相等,返回 0
- 某个index上的字符没有对应的另一字符串Index,返回 字符串长度差值
- 某个index上的字符有对应Index但是Unicode值不同,返回二者Unicode值的差值
很明显, compareTo() 使用比较局限,适合作为low level的底层调用。
> compare() 则可更灵活,比如按照产品的销售区域,价格,销量等多种方式来排序,则可在类中重写compare()方法,或使用匿名类实现该方法,便于以后的sort方法。
class XX {
public int compare(Product p1, Product p2){
return p1.price - p2.price;
}
}
// 匿名类
Collections.sort(list, new Comparator(){
@Override
public int compare(Product p1, Product p2) {
return p1.price - p2.price;
}
}
以上是我的一些粗浅的认识,关于比较这一块有时候的话还得再深入一下。
另外排序也是后续会重点学习的方面,毕竟最基本的算法就是排序算法了。
**如何理解 引用类型的 == 是指向同一个对象? **
我在简书上写了这篇文章,发表后,我分别分享了一份到博客上,一份到我的微信公众号上,
也就是说,我的博客和公众号上都各有一个link指向我的这篇简书文章。
博客和微信的地址类似于Java中的引用,都指向了同一个对象(简书)。所以此时二者可用==表示指向了同一对象。
### 参考文章
[==, .equals(), compareTo(), and compare()](http://www.cnblogs.com/CoolRandy/articles/3676695.html)
Java 比较(==, equals, compareTo, compare)的更多相关文章
- Java中的equals,==,compareTo和compare的比较
Java中的equals(),==,compareTo()和compare() 首先只有==可以用作两个基本类型数据之间的比较,当然是值比较.当用作两个对象比较时,比较的是对象引用,而不是值比较. 其 ...
- Java中“==”、“compareTo()”和“equals()”的区别
在比较两个对象或者数据大小的时候,经常会用到==.compareTo()和equals(),尤其是在接入了Comparable接口后重写compareTo方法等场景,所以我们来理一下这三个的区别. 1 ...
- Android 开发笔记 “java.util.Calendar.compareTo()”
java.util.Calendar.compareTo() 方法比较Calendar对象和anotherCalendar对象之间的时间值(毫秒偏移量). 声明 以下是java.util.Calen ...
- java中的compareto方法的详细介绍
java中的compareto方法的详细介绍 Java Comparator接口实例讲解(抽象方法.常用静态/默认方法) 一.java中的compareto方法 1.返回参与比较的前后两个字符串的as ...
- Java中equals与==和comparaTo的区别
一.先说说Java中equals和==的区别: Java中的数据类型,可分为两类: 1.基本数据类型(也叫原始数据类型) 八大基本数据类型 char byte short int long doubl ...
- Java基础-比较运算符Compare Operators
Java基础-比较运算符Compare Operators 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.关系运算符 关系运算符包括: 1>.大于(>) 2> ...
- java中的compareto方法以及LIst列表排序的详细介绍【转】
java中的compareto方法的详细介绍 javacompareTo java中的compareto方法,返回参与比较的前后两个字符串的asc码的差值,看下面一组代码 String a=&quo ...
- Java的equals方法的使用技巧
Java的equals方法的使用技巧 1.业务场景: 在某个社交软件中,要求每个用户的用户名(name)必须独一无二,那么在每次增加新用户的时候,都要对该用户的注册名进行判断,如果当前用户名已经被占用 ...
- Effective Java —— 覆盖equals时遵守通用约定
本文参考 本篇文章参考自<Effective Java>第三版第十条"Obey the general contract when overriding equals" ...
随机推荐
- 【SysML】用例图
引言 对于系统工程师来说,设计用例图是一种极为常见的建模活动.用例图是一种黑盒视图,通过向读者传递一系列的用例以及相关的参与者,对系统对外提供的服务或系统具备的行为进行建模.在详细讨论SysML的用例 ...
- 版本管理工具 —— SVN
想想我们在开发过程中是不是会遇到这样的情况: 今天写了很长的一段代码,觉得不合理,然后删了,第二天突然发现昨天的那段代码才是正确的,那怎么办,也无法撤销删除的代码? 还有团队中多人共同开发一个项目,如 ...
- JS判断是否为数字或为空
function checkcc() { var reg = new RegExp("^[0-9]*$"); var obj = document.getEleme ...
- SQL一次查出相关类容避免长时间占用表(上)
/* server: db: EDI */ -- 以下案例多次查询同一张表,仅有组合条件Name+Direction不同 --可以使用一次查出相关类容避免长时间占用表 USE EDI GO DECLA ...
- SEO-站内优化规范
类别 要求 实际工作要求 程 序 设 计 1.DIV+CSS布局 2.站内导航连接性良好 面包屑导航,翻页方式使用样式二,文章和产品上一页和下一页 3.图片的ALT属性 在编程时注意写 4.超级链接的 ...
- 读headFirst设计模式 - 装饰者模式
继承可以在复用父类代码的情况下扩展父类的功能,但同时继承增加了对象之间的耦合度,所以要慎用继承.那么有没有既能扩展父类的功能,又能使对象间解耦的方法呢?答案是肯定的,这就是我们今天要学习的装饰者模式. ...
- 记录Winform开发过程中遇到的情况
前两天开发了个Winform操作Excel和数据库的一个小程序,把Winform的一些东西又给捡了起来,当中又学到了一些新的东西,特来写出来留作纪念. 一.CSKIN美化框架的使用 刚开始做的时候,发 ...
- 深入浅出数据结构C语言版(4)——表与链表
在我们谈论本文具体内容之前,我们首先要说明一些事情.在现实生活中我们所说的"表"往往是二维的,比如课程表,就有行和列,成绩表也是有行和列.但是在数据结构,或者说我们本文讨论的范围内 ...
- 【树莓派】Linux 测网速及树莓派源
这篇文章比较杂,其中包含三点:linux环境中测试网络速度,树莓派下载软件的源,部分我写好的脚本: 一.Linux 测网速 Linux 测网速: sar -n DEV 1 100 1代表一秒统计并显示 ...
- JAVA源码剖析(容器篇)HashMap解析(JDK7)
Map集合: HashMap底层结构示意图: HashMap是一个“链表散列”,其底层是一个数组,数组里面的每一项都是一条单链表. 数组和链表中每一项存的都是一“Entry对象”,该对象内部拥有key ...