Obey the general contract when overriding equals

先了解equals 和 == 的区别,如果不重写equals, equals比较的仅仅只是是否引用同一个对象,==更多的是比较基本数值。当我们创建一些对象的时候。

当对象是单例模式不需要进行 equals 重写。

Reflexive: For any non-null reference values x,x.equals(x) must return true.

Symmetric:For any non-null reference values x and y,x.equals(y) must return true if and only if y.equals(x) returns true

Transitive:For any non-null reference values x,y,z,if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) must return true.

Consistent: For any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.

For any non-null reference value x,x.equals(null) must return false.

以及,要明白hashcode的作用,与equals的关系。

package all;

import java.util.Collection;
import java.util.HashSet; public class Test5 { public static void main(String[] args) {
// TODO Auto-generated method stub
Collection c = new HashSet ();
Address s1 = new Address("05");
Address s2 = new Address("05");
c.add(s1);
c.add(s2);
//HashSet()有这个机制,当add的对象发现它hashcode和自己里面已经有的已经相等,自己就会进行相等的对象equals判断,判断为
//相等,set不会储存相同的值,所以就当只存了一个对象。hashcode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable类来存储数据时,都是根据存储对象的hashcode值来进行判断是否相同的。
//详情 http://www.importnew.com/8701.html 关键点 一些collection的比较先从hashcode开始,所以才能快速。
System.out.println("----------------");
System.out.println(s1.equals(s2));
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(c); }
} class Address{
private String addressName;
public Address(String addressName){
this.addressName=addressName;
} public String toString(){
return this.addressName;
} @Override
public boolean equals (Object o){
if (this==o){//对象自身相等原则
return true;
}
if (o==null){//空值返回false 原则
return false;
}
if (o.getClass()!=getClass()){// 类型相同原则
return false;
} Address addr = (Address) o;//之后是实例化进行逻辑比较
if (!addr.addressName.equals(this.addressName)){
return false;
} System.out.println("Use equals!");
return true;
} @Override
public int hashCode(){//hashcode值 很重要,尤其是涉及collection。
return this.addressName.hashCode();
}
}
/*
输出以下:
Use equals!
----------------
Use equals!
true
1541
1541
[05]
会发现在分割线之上凭空多一个 use equals? 这是因为在 hashset 添加的时候,会先进行hashcode 进行比较,一样hashcode值得对象调用equals
比较得出完全一样的对象,根据hashset不重复的特性,最后只有一个值 05 ,如果试着把hashcode 方法去掉 ,则在第一步hashcode值判断就会不一样,
不会进行下一步的 equals 判断,则会输出两个 05,而实际我们希望他们是同一个对象。 */

但是如果集合中已经存在一万条数据或者更多的数据,如果采用equals方法去逐一比较,效率必然是一个问题。此时hashCode方法的作用就体现出来了,当集合要添加新的对象时,先调用这个对象的hashCode方法,得到对应的hashcode值,实际上在HashMap的具体实现中会用一个table保存已经存进去的对象的hashcode值,如果table中没有该hashcode值,它就可以直接存进去,不用再进行任何比较了;如果存在该hashcode值, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址,所以这里存在一个冲突解决的问题,这样一来实际调用equals方法的次数就大大降低了,说通俗一点:Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。

也就是说对于两个对象,如果调用equals方法得到的结果为true,则两个对象的hashcode值必定相等;

  如果equals方法得到的结果为false,则两个对象的hashcode值不一定不同;

  如果两个对象的hashcode值不等,则equals方法得到的结果必定为false;

  如果两个对象的hashcode值相等,则equals方法得到的结果未知。

Cosider implementing Comparable

Comparable 接口的重写有利于 排序,在遇见一些Collection 的时候 。 除了Comparable 还有Comparator ,前者是比较接口 在类中实现,一个是比较器,创建一个类来实现,代码如下。

public class Cat implements Comparable<Cat> {
private int age;
private String name;
public Cat(int age,String name){
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;
} @Override
public int compareTo(Cat o) {//重写比较接口
// TODO Auto-generated method stub return (this.age-o.age);
} } public class MyComparator implements Comparator<Cat>{//比较器的扩展 @Override
public int compare(Cat arg0, Cat arg1) {
// TODO Auto-generated method stub
return (arg1.getAge()-arg0.getAge());
} } public class Test2 { public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ArrayList<Cat> list = new ArrayList<Cat>();
list.add(new Cat(1,"1"));
list.add(new Cat(5,"5"));
list.add(new Cat(2,"2"));
list.add(new Cat(4,"4"));
list.add(new Cat(3,"3"));
Collections.sort(list);
for (Cat a:list){
System.out.println(a.getAge());
}
Collections.sort(list, new MyComparator());
for (Cat a:list){
System.out.println(a.getAge());
} } } /*
输出
1
2
3
4
5
5
4
3
2
1
*/

Effective Java Methods Common to All Objects的更多相关文章

  1. Effective Java 05 Avoid creating unnecessary objects

    String s = new String("stringette"); // Don't do this. This will create an object each tim ...

  2. Effective Java P2 Creating and Destroying Objects

    This chapter concerns creating and destorying objects : when and how to create them, when and how to ...

  3. Effective Java Index

    Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...

  4. Effective Java 第三版笔记(目录)

    <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时 ...

  5. Effective Java 目录

    <Effective Java>目录摘抄. 我知道这看起来很糟糕.当下,自己缺少实际操作,只能暂时摘抄下目录.随着,实践的增多,慢慢填充更多的示例. Chapter 2 Creating ...

  6. 【Effective Java】阅读

    Java写了很多年,很惭愧,直到最近才读了这本经典之作<Effective Java>,按自己的理解总结下,有些可能还不够深刻 一.Creating and Destroying Obje ...

  7. 《Effective Java》读书笔记 - 3.对于所有对象都通用的方法

    Chapter 3 Methods Common to All Objects Item 8: Obey the general contract when overriding equals 以下几 ...

  8. Effective Java 创建和销毁对象

    <Effective Java>阅读笔记,用适合自己理解的方式提炼该书内容.<Effective Java>是一本很实用的书,阅读方法应该是快速的领会,总结,然后应用.而非,一 ...

  9. Effective Java 第三版——11. 重写equals方法时同时也要重写hashcode方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. win10+cpu+tensorflow+pycharm

    1.安装64位的python3.5 选择windowsx86-64 executable installer安装 2.安装tensorflow cmd->进入到安装python的Scripts文 ...

  2. php中安装memcache

    1.查看php的版本(我的是5.6) 2.打开phpinfo查看第四行 3.然后选择要安装的文件 4.复制到 ext中 复制后 5.打开配置文件php.ini 把 extension=php_memc ...

  3. 正睿 2018 提高组十连测 Day2 T2 B

    题目链接 http://www.zhengruioi.com/contest/84/problem/318 题解写的比较清楚,直接扒过来了. B 算法 1 直接按题意枚举,动态规划或是记忆化搜索. 时 ...

  4. 基于Mybatis实现一个查库的接口

    基本功能就是写一个接口,该接口的主要功能是根据给的条件查询特定表: 先通过Workbench来看一下在给定条件下的查询的结果,先给出最终的结果查询的表以及查询的条件: 也就是该接口实现在image_t ...

  5. 『Github』本地项目更新到服务器

    对于已经新建到服务器的项目,我们在本地有了新的修改之后,想要同步到服务器时的操作. 1.clone代码 1.把目标工程clone到本地,使用指令: >git clone https://gith ...

  6. 【其他】【PL/SQL Developer】【1】解决PL/SQL Developer过期的情况

    正文: 1,开始菜单,搜索regedit,回车打开(即日常搜索电脑安装的软件的地方,regedit就是注册表) 2,按HKEY_CURRENT_USER\Software\Allround Autom ...

  7. Object.keys的使用

    链接:https://www.nowcoder.com/questionTerminal/52c41b84e32a4158883cb112a1d1f850来源:牛客网 输出对象中值大于2的key的数组 ...

  8. 灵活运用 SQL SERVER FOR XML PATH 转

    灵活运用 SQL SERVER FOR XML PATH   FOR XML PATH 有的人可能知道有的人可能不知道,其实它就是将查询结果集以XML形式展现,有了它我们可以简化我们的查询语句实现一些 ...

  9. MongoDB 教程(三):MongoDB 的下载、安装和配置

    一.下载 下载地址:https://www.mongodb.com/download-center#community(这里是Windows 版,其他版本也可以在该网页进行下载) 版本选择: Mong ...

  10. git忽略未被跟踪和已被跟踪的文件

    git的文件操作本质上来讲是基于文件索引来做追踪的.   至于忽略未跟踪(untrack)文件文件,git提供了三种方式 1 .gitignore 2 git config --global core ...