Java hashCode
来源:互联网 发布:python 矩阵转图片 编辑:程序博客网 时间:2024/06/01 08:45
Java 使用hashCode意在提高查询效率。
首先java在比较2个对象是否相等的时候会比较hashCode,如果hashCode相等 ,会再去比较对象是否equals;如果hashCode不等就直接判定2个对象不等。(这里有个原则:如果2个对象equals 则hashCode一定相等,如果hashCode相等 却不一定equals)
public class HashCodeTest {
public static void main(String[] args) {
Person p1 = new Person(000, "lisi");
Person p2 = new Person(001, "lisi");
Person p3 = new Person(002, "zhangshan");
System.out.println(p1.hashCode());//p1与p2的hashCode相等
System.out.println(p2.hashCode());
System.out.println(p3.hashCode());
System.out.println(p1.equals(p2));//p1与p2不相等
System.out.println(p1.equals(p3));
}
}
class Person{
int id;
String name;
public Person(int pId,String pName){
this.id = pId;
this.name = pName;
}
@Override
public int hashCode() {
return this.name.hashCode();
}
@Override
public String toString() {
return this.id + " : " + this.name;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (id != other.id)
return false;
if(name != other.name)
return false;
return true;
}
}
equals与hashCode方法都来自于Object类,而Object类的hashCode和equals都是比较2个对象是否是同一个对象 (即比较的是==)。必需清楚 String 、Math、Integer、Double等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法。
要比较2个对象是否相等必须重写equals,重写equals又必须重写hashCode方法。这是由于Java在比较调用equals()之前先会调用hashCode。所以 如果只重写equals方法而不重写hashCode方法,在比较时会调用父类(Object)的hashCode方法,这样就失去了写equals的意义。
之所以在比较之前会使用hashCode,原因就在于这篇文章的标题(提交查询效率)。
以下例子使用了上面的Person类
public static void main(String[] args) {
Person p1 = new Person(000, "lisi");
Person p2 = new Person(0001, "lisi");
Person p3 = new Person(000, "zhangshan");
Person p4 = new Person(000, "zhangshan");
Collection<Person> collection = new HashSet<Person>();
collection.add(p1);
collection.add(p2);
collection.add(p3);
collection.add(p4);
for (Person p : collection) {
System.out.println(p);
}
}
大家应该都知道,set容器是装的是无序不可重复的元素,所以 collection.add()改动作会去查询当前待加入的对象是否在collection中是否已存在。试想,如果collection中已有很多元素,那么会用equals去一个一个比较collection中的每一个元素,这样其实很蠢、效率很低。所以使用了hashCode解决了次问题。
HashCode原理浅析:使用hash算法实现的容器会对立面的元素进行分区(按照hashCode值来分的),当在add元素时会对元素计算出一个hashCode码(至于Java是怎么样计算的我们并不关心),然后根据这个码查询应该添加到容器的哪一个区域(这样避免了一个一个大量比较每一个元素带来的时间)。
HashCode带来的内存泄露问题(只是表面,java中有GC回收)。
public static void main(String[] args) {
Person p1 = new Person(000, "lisi");
Person p2 = new Person(001, "lisi");
Person p3 = new Person(000, "zhangshan");
Collection<Person> collection = new HashSet<Person>();
collection.add(p1);
collection.add(p2);
collection.add(p3);
p2.name = "wangwu";
collection.remove(p2);//p2没有remove成功
collection.remove(p3);//p3成功remove
for (Person p : collection) {
System.out.println(p);
}
}
原因在于:当collection已经把p2加入容器后,根据p2的hashCode码在collection的位置已经确定了,而之后改变了p2对象中的name属性,则p2的hashCode码就变了。然后去 collection.remove(p2)时p2的hashCode码在collection中的特定区域内并不存在,所以会认为collection中斌没有p2对象,这就造成了p2没有remove成功的现象。
注意:只有使用hash算法实现的容器在比较元素时才会使用hashCode方法,如HashSet,HashMap,HashTable.....。故使用Hash的效率较高。
- Java HashCode
- java hashCode
- Java hashCode
- Java HashCode
- Java HashCode
- Java hashCode
- JAVA HashCode
- Java HashCode
- 【Java】HashCode
- java hashcode()
- java hashCode
- java hashcode
- java hashcode
- Java hashCode
- java hashCode
- java hashcode
- Java hashcode
- 【java】hashCode
- Html+CSS CSS3中 transitions属性详解
- ViewPager左右滑动页面,下面的按钮跟着动态变化
- java0x01 eclipse基本操作
- linux下svn配置
- Python中的陷阱
- Java hashCode
- EventBus源码解读详细注释(5)事件消息继承性分析 eventInheritance含义
- 获取指定时间的offsets类:GetOffsetShell 源码导读
- 跟着Google学Android —— 1.3 来创建个非常简单的UI吧
- 1.1. Creating a New Project from Maven Archetype 从Maven Archetype创建一个新项目
- OC中关于时间的几个函数及格式化时间
- AlertController工具类的封装,让AlertController变得更简单
- 数组去重
- 车牌识别中的车牌定位