java HashCode()方法理解
2015-11-24 19:56
399 查看
hashcode()方法相信大家都知道这是在Object中定义的方法,估计很多人不知道它是干嘛用的,今天在imageLoader框架源码时遇到的,于是,也学习下,在这说一句,看框架源码真是可以学到很多知识!
比如Set集合我们都知道它是不能存放重复的数据,那么它是怎么做到的呢?它会涉及到hash算法了,
如果我们每次加入一个数据都要用equals方法来判断时,当数据到几万或者几十万时候,这样遍历进行判断,效率就变低了,
java为了提升效率就引入了哈希表的算法,也就是哈希算法了!
hash算法原理:
当Set接收一个元素时根据该对象的内存地址算出hashCode,看它属于哪一个区间,在这个区间里调用equeals方法,
如果哈希不一样就不是同一个数据了,这样就不用equals进行判断了,是不是省略了遍历进行equals判断,从而提高了效率~
确实提高了效率。但发现一个问题:若两个对象equals相等,但不在一个区间,根本没有机会进行比较,会被认为是不同的对象。所以Java对于eqauls方法和hashCode方法是这样规定的:
1 如果两个对象相同,那么它们的hashCode值一定要相同。也告诉我们重写equals方法,一定要重写hashCode方法。
2 如果两个对象的hashCode相同,它们并不一定相同,这里的对象相同指的是用eqauls方法比较。
现在写个例子进行比较:
这就验证了第一个结论是正确的:
如果两个对象相同,那么它们的hashCode值一定要相同。也告诉我们重写equals方法,一定要重写hashCode方法
那么怎么验证第二个结论是否正确呢?很简单,不要重写equals方法就ok
比如Set集合我们都知道它是不能存放重复的数据,那么它是怎么做到的呢?它会涉及到hash算法了,
如果我们每次加入一个数据都要用equals方法来判断时,当数据到几万或者几十万时候,这样遍历进行判断,效率就变低了,
java为了提升效率就引入了哈希表的算法,也就是哈希算法了!
hash算法原理:
当Set接收一个元素时根据该对象的内存地址算出hashCode,看它属于哪一个区间,在这个区间里调用equeals方法,
如果哈希不一样就不是同一个数据了,这样就不用equals进行判断了,是不是省略了遍历进行equals判断,从而提高了效率~
确实提高了效率。但发现一个问题:若两个对象equals相等,但不在一个区间,根本没有机会进行比较,会被认为是不同的对象。所以Java对于eqauls方法和hashCode方法是这样规定的:
1 如果两个对象相同,那么它们的hashCode值一定要相同。也告诉我们重写equals方法,一定要重写hashCode方法。
2 如果两个对象的hashCode相同,它们并不一定相同,这里的对象相同指的是用eqauls方法比较。
现在写个例子进行比较:
public class User { private String name; private int age; public User(String name, int age) { super(); this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if(obj==null){ return false; } User user = (User) obj; return this.name==user.name&&this.age==user.age; } @Override public int hashCode() { return age; } }Test.java测试
public class Test { public static void main(String[] args) { User user1 = new User("zgz",1); User user2 = new User("zgz",1); System.out.println("user1="+user1); System.out.println("user2="+user2); System.out.println(user1.equals(user2)); } }这个时候equals调用的就不是Object方法中的equals的方法了,这个时候打印出来的是true,表示这user1和user2是同一个对象
这就验证了第一个结论是正确的:
如果两个对象相同,那么它们的hashCode值一定要相同。也告诉我们重写equals方法,一定要重写hashCode方法
那么怎么验证第二个结论是否正确呢?很简单,不要重写equals方法就ok
相关文章推荐
- JAVA中String类的常见操作
- JVM (2)-- JVM内存模型
- java中导入类
- 如何配置 struts2 可以受理的请求的扩展名
- Eclipse启动出错:Failed to load the JNI shared library
- 关于Java类初始化和实例化中的2个“雷区”
- java容器详解
- Spring AOP详细用法
- Java 十进制转十六进制
- spring 缓存 @CachePut 和 @Cacheable 区别
- myeclipse中SVN插件安装遇到的问题:Failed to load JavaHL Library
- Java实现打包下载BLOB字段中的文件
- eclipse字体设置方法
- 浅谈java代理
- 核心java系列——异常处理
- Java char[]转String的两种方式
- 通过java读取HDFS的数据 (转)
- Java实现下载BLOB字段中的文件
- Eclipse中自动提示的方法参数都是arg0,arg1的解决方法
- 在eclipse的工具栏中不显示Android SDK and AVD Manager