为什么要重写hashCode()方法和equals()方法及如何重写
我想写的问题有三个:
1、首先我们为什么需要重写hashCode()方法和equals()方法
2、在什么情况下需要重写hashCode()方法和equals()方法
3、如何重写这两个方法
*********************************************************************
第一个问题:为什么需要重写hashCode()方法和equals()方法
Java中的超类Object类中定义的equals()方法是用来比较两个引用所指向的对象的内存地址是否一致
Object类中equals()方法的源码
public boolean equals(Object obj) {
return (this == obj);
}
Object类中的hashCode()方法,用native关键字修饰,说明这个方法是个原生函数,也就说这个方法的实现不是用java语言实现的,是使用c/c++实现的,并且被编译成了DLL,由java去调用,jdk源码中不包含。对于不同的平台它们是不同的,java在不同的操作系统中调用不同的native方法实现对操作系统的访问,因为java语言不能直接访问操作系统底层,因为它没有指针。
这种方法调用的过程:
1、在java中申明native方法,然后编译
2、用javah产生一个 .h 文件
3、写一个 .cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(其中又包含了jdk带的jni.h文件);
4、将.cpp文件编译成动态链接库文件
5、在java中用System.loadLibrary()文件加载第四步产生的动态链接库文件,然后这个navite方法就可被访问了
Java的API文档对hashCode()方法做了详细的说明,这也是我们重写hashCode()方法时的原则【Object类】
重点要注意的是:
a. 在java应用程序运行时,无论何时多次调用同一个对象时的hsahCode()方法,这个对象的hashCode()方法的返回值必须是相同的一个int值
b. 如果两个对象equals()返回值为true,则他们的hashCode()也必须返回相同的int值
c. 如果两个对象equals()返回值为false,则他们的hashCode()返回值也必须不同
public native int hashCode();
现在到了说正题了,为什么要重写
我们在定义类时,我们经常会希望两个不同对象的某些属性值相同时就认为他们相同,所以我们要重写equals()方法,按照原则,我们重写了equals()方法,也要重写hashCode()方法,要保证上面所述的b,c原则;所以java中的很多类都重写了这两个方法,例如String类,包装类
4、第二个问题:在什么情况下需要重写hashCode()方法和equals()方法
当我们自定义的一个类,想要把它的实例保存在集合中时,我们就需要重写这两个方法;集合(Collection)有两个类,一个是List,一个是Set
List:集合中的元素是有序的,可以重复的
Set:无序,不可重复的
以HashSet来说明:
HashSet存放元素时,根据元素的hashCode值快速找到要存储的位置,如果这个位置有元素,两个对象通过equals()比较,如果返回值为true,则不放入;如果返回值为false,则这个时候会以链表的形式在同一个位置上存放两个元素,这会使得HashSet的性能降低,因为不能快速定位了。还有一种情况就是两个对象的hashCode()返回值不同,但是equals()返回true,这个时候HashSet会把这两个对象都存进去,这就和Set集合不重复的规则相悖了;所以,我们重写了equals()方法时,要按照b,c规则重写hashCode()方法!
5、第三个问题:如何重写这两个方法
我写了一个例子,大家可以看一下
*******************************************************************************
package cn.hashCode.jing;
/**
*定义一个Ponint测试类,用来测试Set集合保存元素的方式中
*hashCode()方法和equals()方法对Set集合保存元素影响
*
*/
public final class Point {
private int x;
private int y;
public Point(){
super();
}
public Point(int x,int y){
this.x=x;
this.y=y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public boolean equals(Object obj){
if(this==obj){
return true;
}
if(obj!=null && obj.getClass()==Point.class){
Pointpo=(Point)obj;
if(this.x==po.x && this.y==po.y){
return true;
}
}
return false;
}
@Override
public int hashCode(){
return 7*x+31*y;
}
/*以下是自动生成的
@Override
publicboolean equals(Object obj) {
if(this == obj)
returntrue;
if(obj == null)
returnfalse;
if(getClass() != obj.getClass())
returnfalse;
Pointother = (Point) obj;
if(x != other.x)
returnfalse;
if(y != other.y)
returnfalse;
returntrue;
}
@Override
publicint hashCode() {
finalint prime = 31;
intresult = 1;
result= prime * result + x;
result= prime * result + y;
returnresult;
}*/
public String toString(){
return x+","+y+" ";
}
}
package cn.hashCode.jing;
import java.util.HashSet;
public class TestHashSet {
public static void main(String[] args) {
HashSet<Point>hs=new HashSet<Point>();
Pointp1=new Point(3,4);
Pointp2=new Point(6,4);
Pointp3=new Point(10,7);
Pointp4=new Point(8,9);
Pointp5=new Point(3,4);
hs.add(p1);
hs.add(p2);
hs.add(p3);
hs.add(p4);
hs.add(p5);
System.out.println(p1.equals(p5));
System.out.println(p1.hashCode());
System.out.println(p5.hashCode());
System.out.println(hs);
}
}
结果:true
145
145
[3,4 , 6,4 , 10,7 ,8,9 ]
可以自己试一下,hashCode()返回值相等,equals()返回false;和hashCode()返回值不相等,equals()返回值为true;都会出现什么情况
为什么要重写hashCode()方法和equals()方法及如何重写的更多相关文章
- 为什么要重写hashcode方法和equals方法
我们可能经常听到说重写equals方法必须重写hashcode方法,这是为什么呢?java中所有的类都是Object的子类,直接上object源码 /* * Copyright (c) 1994, 2 ...
- Java 重写hashCode 方法和equals方法
package Container; import java.util.HashSet; import java.util.Iterator; /* Set 元素是无序的(存入和取出的顺序不一定一致) ...
- hashCode()方法和equals方法的重要性。
在Object中有两个重要的方法:hashCode()和equals(Object obj)方法,并且当你按ctrl+alt+s时会有Generator hashCode()和equals().我们不 ...
- java 集合 HashSet 实现随机双色球 HashSet addAll() 实现去重后合并 HashSet对象去重 复写 HashCode()方法和equals方法 ArrayList去重
package com.swift.lianxi; import java.util.HashSet; import java.util.Random; /*训练知识点:HashSet 训练描述 双色 ...
- hashCode方法和equals方法比较
为什么用HashCode比较比用equals方法比较要快呢?我们要想比较hashCode与equals的性能,得先了解HashCode是什么. HashCode HashCode是jdk根据对象的地址 ...
- 【转】为什么要重写hashcode()方法和toString()方法
Object 类 包含toString()和hashCode()方法. 一.toString(): 在Object类里面定义toString()方法的时候返回的对象的哈希code码,这个hashcod ...
- 集合hashCode()方法和equals()办法
1.哈希码: Object中的HashCode方法会返回该对象的的内存真实地址的整数化表示,这个形象的不是真正抵制的整数值就是哈希码. 2.利用哈希码向集合中插入数据的顺序? ...
- java数组、java.lang.String、java.util.Arrays、java.lang.Object的toString()方法和equals()方法详解
public class Test { public static void main(String[] args) { int[] a = {1, 2, 4, 6}; int[] b = a; in ...
- Object、String、数组的 toString() 方法和 equals() 方法及java.util.Arrays
public class Test { public static void main(String[] args) { int[] a = {1, 2, 4, 6}; int[] b = a; in ...
随机推荐
- SideBar 选择城市时右侧边上的 选择bar
需要定义一个SideBar的视图类 在布局文件中引用 同时在布局中设置一个textView默认不可见 当触摸时才显示 在调用的Activity中 sideBar.setOnTouchingL ...
- c语言使用指针对int数组的求和
#include <stdio.h> int sump(int *, int *); int main(void) { , , , , }; printf()); ; } int sump ...
- winform closing事件注册
参考链接:http://blog.chinaunix.net/uid-215617-id-2213081.html
- 进程同步(multiprocess.Lock、multiprocess.Semaphore、multiprocess.Event) day38
进程同步(multiprocess.Lock.multiprocess.Semaphore.multiprocess.Event) 锁 —— multiprocess.Lock 通过刚刚的学习,我们千 ...
- c# 24种设计模式
备忘录模式(Memento Pattern) 策略模式(Strategy Pattern) 抽象工厂模式(Abstract Factory Pattern) 代理模式(Proxy Pattern) 单 ...
- 修改JEECG项目浏览器标题
方法1: 在线修改,在平台自带的功能“系统管理”——“国际化语言” 中搜索 jeect.platform,修改显示文字重启生效. 方法2: 修改数据表t_s_muti_lang中id为"40 ...
- ParseCrontab类,解析时间规则
<?php /** * Created by PhpStorm. * User: ClownFish 187231450@qq.com * Date: 14-12-27 * Time: 上午11 ...
- BZOJ 1799 - [AHOI2009]self 同类分布 - 枚举 数位DP
Description 找出$[L, R]$ 区间内有多少数, 各位数字和 能整除原数 Solution 枚举每个可能的数字和, 进行数位DP即可 , 水爆 Code #include<cstd ...
- BUG(0):用某位表示特定属性
用某个bit表示特定属性通常有两种方式: 1.指定某个特定的value #define _PAGE_VALID 0x0001 0bit 为 1 时表示此时的page entry是有效的 用法如下,此时 ...
- websocket activemq
websocket:应用与服务端保持长连接 不停通信 activemq:偶发通信 心跳机制