一.首先明确一点:equals()方法和hashcode()方法是Object类里的方法

  查看源码可以知道,在Object类中equals(obj)方法直接返回的是  this == obj 的值。对于引用变量来说,这个式子判断的是变量中存储的内存地址是否一致。而hashcode()方法的出现,目的是为了提高哈希表的性能,也就是说,提供这样一个方法是为了提高依据hashcode进行存取的数据结构的性能的。

 两者的关系:

 在Object类的注释中可以看到两个原则:

 两个类如果通过equals()方法比较返回的值为true,则这两个类调用hashcode()方法返回的整数值必须相等。

 两个类如果通过equals()方法比较返回的值为false,则这两个类调用hashcode()方法返回的整数值建议不同(hashcode的初衷),可以相等。

 故在Object类中:

 equals()方法比较的方式是比较两个引用的内存地址,对于任何新 new 出来的对象来说,他们的内存地址都是不一样的。而Object类默认的hashcode计算方式和类的内存地址相关,所以他们的hashcode是不同的。

package com.njsteel.test;

public class Test {
public static void main(String[] args){ Object obj1 = new Object();
Object obj2 = new Object();
Object obj3 = obj1; obj1.hashCode();//
obj2.hashCode();//
obj3.hashCode();// obj1.equals(obj2);//false
obj1.equals(obj3);//true
}
}

  故,我们自定义的所有类,如果没有重写equals()方法和hashcode()方法,则都是满足上述的情况的。因为自定义的类都是Object类的子类。

二. 其次,Java提供的很多便捷类都会重写equals()和hashcode()方法。

   这里只说明一下String类的情况。

为什么String类要重写equals()和hashcode()方法?

一般来说,当我们想判断两个String类对象的内容是否相同时,我们就会调用equals()方法,这是API文档告诉我们的。我们比较时,一般是两个不同对象的引用。这时候,即使String对象的内容相同,如果按照Object类里equals()的判断方法判断,返回的值始终都是false。

所以为了满足这样的需要,String类equals()方法重写添加了根据内容判断两个String对象内容是否相同的逻辑代码。

equals()被重写后,hashcode()自然也要被重写,因为重写的equals()方法破坏了Object类中规定的两者的关系。于是String类里的hashcode()方法也重写成了和String内容相关的样子。以满足原来的关系。

其他的类就可以按照这样的情况以此类推。。

三. 和某些集合类的关系

先说Set:

在看书的时候,对于Set的描述有:Set集合不允许包含相同的元素

在Set里,相同的元素是指通过equals()方法返回值为true的两个对象。在调用Set的add()方法时,就会进行这个判断(add进来的元素会与Set集合里已经有的所有元素进行equals判断,如果有相同,则add()方法返回false,添加失败)。

对于HashSet类:

HashSet是Set接口的一个实现,自然也是不允许包含相同的元素。不过判断的方法和原始的Set有点不同。

往HashSet集合里添加元素时,它不仅会通过equals()方法判断,还要调用hashcode()方法判断。只有当两个元素equals相等,并且hashcode也相等时,两个元素才是相同的元素。当其中有一个方法比较显示两个元素不一样时,HashSet会将其添加。

对于HashMap类:

我们知道HashMap的Key值是不能重复的。其实HashMap的Key值是保存在一个Set()集合里的。所以,作为Key,至少他们的hashcode是不相同的。如果两个对象是相同的Key(equals相等,hashcode也相同),值会覆盖。

验证代码:

package com.njsteel.test;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set; public class HashSetTest {
public static void main(String[] args){
Set<MyString> set_1 = new HashSet<MyString>();
MyString myString1 = new MyString();
MyString myString2 = new MyString();
//添加一个元素
set_1.add(myString1);
//添加一个equals返回true,但是hashcode不同的元素
System.out.println(myString1.equals(myString2)+"!!!"+myString1.hashCode()+"/"+myString2.hashCode());
System.out.println(set_1.add(myString2));//true,添加成功。 //添加一个元素
Set<MyTestObject> set_2 = new HashSet<MyTestObject>();
set_2.add(new MyTestObject());
//添加一个equals返回false,但是hashcode相同的元素。
System.out.println(set_2.add(new MyTestObject())+""+set_2.size()); Map<MyString,String> map = new HashMap<MyString,String>(); map.put(myString1, "1");
map.put(myString2, "2");
for(Object key : map.keySet()){
System.out.println(map.get(key));
} }
} class MyString{ @Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return true;
} @Override
public int hashCode() {
// TODO Auto-generated method stub
return super.hashCode();
} } class MyTestObject{ @Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return false;
} @Override
public int hashCode() {
// TODO Auto-generated method stub
return 1;
} }
 
 欢迎讨论指正。。

关于equals、hashcode和集合类的小结的更多相关文章

  1. equals(),hashcode(),克隆学习心得

    equals(),hashcode(),克隆学习心得 其实在开发时候,很少去重写equals(),hashCode()方法,但是有些时候业务需要还是要重写. 注意: 重写equals()方法一定要重写 ...

  2. 讲的很详细的一篇关于object equals() & hashCode() 的文章

    转: 讲的很详细的一篇关于object equals() & hashCode() 的文章 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java ...

  3. java中的 equals + hashCode

    [0]README 0.1)本文转自 core java volume 1, 旨在理清 equals + hashCode方法: [1]equals方法 1.1) Object中的 equals 方法 ...

  4. JavaSE的包装类,自动装箱和自动拆箱 ,字符窜转换,toString(),equals(), hashCode()的区别

    一.基本数据类型和包装类 包装类均位于Java.lang包,包装类和基本数据类型的对应关系如下表所示: Primitive-Type   Wrapper-Class        byte       ...

  5. 在@Data注释lombok上使用继承警告等于/ hashCode(Warning equals/hashCode on @Data annotation lombok with inheritance)

    生成equals / hashCode实现但没有调用超类,即使这个类没有扩展java.lang.Object.如果这是故意的,请将 @EqualsAndHashCode(callSuper = fal ...

  6. == equals hashCode 总结比较

    在Java中: ==是运算符,用于比较两个变量是否相等. equals,是Objec类的方法,用于比较两个对象是否相等,默认Object类的equals方法是比较两个对象的地址,跟==的结果一样.Ob ...

  7. equals(),hashcode()方法详解

    Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要重写这两个方法,今天就来介绍一些这两个方法的作用. equals ...

  8. 借助强大的IDEA开发ide高效实现equals,hashcode以及toString方法

    IDEA工具提供多种生成hashCode与equals的代码方案,注意:尽量不要使用第一个方案,第一个方案对于null不做判空处理,容易NNP问题. 对于生成toString方法方案,默认使用的是+拼 ...

  9. equals hashcode toString 方法的使用

    package com.wu.toString; import java.util.Date; import java.util.GregorianCalendar; /** * * @author ...

随机推荐

  1. Virtualbox虚拟机配置CentOS7.0静态网络

    1.首先在Virtualbox下将网络设置为Bridged Adapter,此项设置可以使本机与虚拟机进行互访,而NAT模式只能进行单项访问: 2.先切换到root,配置网卡信息需要用到root,然后 ...

  2. iOS计算完整文字高度(适应iOS 10)

    动态计算文字的高度:(切记LineSapcing>=2,不然会显示不全) +(CGSize) boundingALLRectWithSize:(NSString*) txt Font:(UIFo ...

  3. NET基础(3):is 和 as 操作符

    在C#语言中进行类型转换的另外一种方式是使用is和as操作符.is检查对象是否兼容于指定类型,返回Boolean值true或false.注意,is操作符永远不抛出异常,例如以下代码: Object o ...

  4. C++数组实现的循环队列

    #include<iostream> #include <string> /* 功能:数组实现的循环队列,C++实现,学习参考 */ using namespace std; ...

  5. Find linux下

    find 1.作用 find命令的作用是在目录中搜索文件,它的使用权限是所有用户. 2.格式 find [path][options][expression] path指定目录路径,系统从这里开始沿着 ...

  6. Keras学习~试用卷积~跑CIFAR-10

    import numpy as np import cPickle import keras as ks from keras.layers import Dense, Activation, Fla ...

  7. android 命令编译

    引用:http://jojol-zhou.iteye.com/blog/729254 Android 命令行手动编译打包过程图  [详细步骤]: 1使用aapt生成R.java类文件: 例: F:\e ...

  8. WSF脚本详解:组合JS和VBS代码

    1.概述 Windows Script Host除了提供一个对象模型之外,还提供了一种脚本框架,这就是WSF脚本.通过WSF约定的标记元素,可以将多种脚本语言写的代码块组合起来,完成任务.除此之外,还 ...

  9. Xubuntu VNC Xfce4

    sudo mousepad ~/.vnc/xstartup #!/bin/sh # Uncomment the following two lines for normal desktop: unse ...

  10. Install Jenkins Slave as Windows Service

    https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins+as+a+Windows+service SC 直接创建windows s ...