1. public native int hashCode();

返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。

一、HashCode的作用

  我们通常会用equals判断集合中是否包含一个对象,这种方式需要遍历集合中每一个元素,然后对他们一一进行equals方法比较。对于少量数据的集合该方式自然可以,但当我们的数据很多例如一万个,如果还使用这种逐个遍历的方式显然不合适。于是有人发明了一种哈希算法来提高从集合中查找元素的效率。这种方式的核心就是将集合分为若干个区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,查找对象时我们先根据对象的哈希码来确定该对象存储在某个区域。然后在这个区域内查找元素。

在java中HashSet、HashMap以及HashTable这些散列集合,就是与hashCode方法一起使用。

下面这段代码是java.util.HashMap的中put方法的具体实现:

  1. public V put(K key, V value) {
  2. if (table == EMPTY_TABLE) {
  3. inflateTable(threshold);
  4. }
  5. if (key == null)
  6. return putForNullKey(value);
  7. int hash = hash(key);
  8. int i = indexFor(hash, table.length);
  9. for (Entry<K,V> e = table[i]; e != null; e = e.next) {
  10. Object k;
  11. if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
  12. V oldValue = e.value;
  13. e.value = value;
  14. e.recordAccess(this);
  15. return oldValue;
  16. }
  17. }
  18.  
  19. modCount++;
  20. addEntry(hash, key, value, i);
  21. return null;
  22. }

  put方法是用来向HashMap中添加新的元素,从put方法的具体实现可知,会先调用hashCode方法得到该元素的hashCode值,然后查看table中是否存在该hashCode值,如果存在则调用equals方法重新确定是否存在该元素,如果存在,则更新value值,否则将新的元素添加到HashMap中。从这里可以看出,hashCode方法的存在是为了减少equals方法的调用次数,从而提高程序效率。

二、equals与HashCode

1、equals与HashCode必须一起出现

在put()方法中为什么判断HashCode后还要判断equals?

因为不同的对象可能会生成相同的hashcode值,所以我们不能根据hashcode值判断两个对象是否相等。但是可以直接根据hashcode值判断两个对象不等,如果两个对象的hashcode值不等,则必定是两个不同的对象。如果要判断两个对象是否真正相等,必须通过equals方法。

所以我们在重写equals方法时一定要重写hashcode方法。因为散列集合在添加数据的时候会先判断对象的hashCode值,hashcode值不同,他们就会被散列在不同的存储区域,所以接下来再比较equals的时候已经没有意义了,这个时候就违背了集合的意义(不允许重复元素的 集合)。

2、保证集合中的对象的hashcode值不能改变

当一个对象被存储在散列集合后,就不能修改这个对象中的哪些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存入集合时的哈希值不相等了,在这中情况中,即使在contains方法使用该对象的当前引用作为参数去散列集合中检索对象,也将出现找不到对象的结果,这将会导致无法从散列集合中单独删除当前对象,从而照成内存溢出。

使用HashSet演示:

  1. package com.jalja.org.base.test;
  2.  
  3. import java.util.HashSet;
  4. import java.util.Set;
  5.  
  6. public class Point {
  7. private int x;
  8. private int y;
  9.  
  10. public Point(int x, int y) {
  11. super();
  12. this.x = x;
  13. this.y = y;
  14. }
  15. public int getX() {
  16. return x;
  17. }
  18. public void setX(int x) {
  19. this.x = x;
  20. }
  21. public int getY() {
  22. return y;
  23. }
  24. public void setY(int y) {
  25. this.y = y;
  26. }
  27.  
  28. @Override
  29. public int hashCode() {
  30. final int prime = 31;
  31. int result = 1;
  32. result = prime * result + x;
  33. result = prime * result + y;
  34. return result;
  35. }
  36. @Override
  37. public boolean equals(Object obj) {
  38. if (this == obj)
  39. return true;
  40. if (obj == null)
  41. return false;
  42. if (getClass() != obj.getClass())
  43. return false;
  44. Point other = (Point) obj;
  45. if (x != other.x)
  46. return false;
  47. if (y != other.y)
  48. return false;
  49. return true;
  50. }
  51. public static void main(String[] args) {
  52. Point point1=new Point(1,2);
  53. Point point2=new Point(2,3);
  54. Point point3=new Point(3,4);
  55. Set<Point> set=new HashSet<Point>();
  56. set.add(point1);
  57. set.add(point2);
  58. set.add(point3);
  59. System.out.println(set.size());//
  60. point1.setX(5);//改变 point1的x值
  61. set.remove(point1);//移除 point1
  62. System.out.println(set.size());//
  63. }
  64. }

从结果可以看出 point1已经无法删除了。

JAVA学习之HashCode的更多相关文章

  1. 0025 Java学习笔记-面向对象-final修饰符、不可变类

    final关键字可以用于何处 修饰类:该类不可被继承 修饰变量:该变量一经初始化就不能被重新赋值,即使该值跟初始化的值相同或者指向同一个对象,也不可以 类变量: 实例变量: 形参: 注意可以修饰形参 ...

  2. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

  3. JAVA学习第三十六课(经常使用对象API)— Set集合:HashSet集合演示

    随着Java学习的深入,感觉大一时搞了一年的ACM,简直是明智之举,Java里非常多数据结构.算法类的东西,理解起来就轻松多了 Set集合下有两大子类开发经常使用 HashSet集合 .TreeSet ...

  4. 201521123105 第四周Java学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 继承与多态的概念与实现父类与之类的关系解决代码复用的办法 2. 书面作业 2.1 将在网上商 ...

  5. java学习(三)

    学号 20189214 <Java程序设计>第三周学习总结 教材学习内容总结 核心类 java.lang.Object 所有的类都直接派生自这个类. java.lang.String St ...

  6. Java 基础:hashCode方法

    Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 一.前言 泥瓦匠最近被项目搞的天昏地暗.发现有些要给自己一些目标,关于技术的目标: 专注很重要.专注J ...

  7. Java学习:注解,反射,动态编译

    狂神声明 : 文章均为自己的学习笔记 , 转载一定注明出处 ; 编辑不易 , 防君子不防小人~共勉 ! Java学习:注解,反射,动态编译 Annotation 注解  什么是注解 ? Annotat ...

  8. Java学习个人总结

    声明:个人原创,转载请在文章开头明显位置注明出处:https://www.cnblogs.com/sunshine5683/p/10063960.html 学习从来都是一个阶段的学习,然后进行整理与总 ...

  9. java学习笔记13--反射机制与动态代理

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...

随机推荐

  1. 使用idea上传项目到gitHub

    上传项目到gitHub 创建好后开始提交本地项目代码如图: 选中VCS选中图中的按钮如图所示: 然后再选中Src点中add按钮如图所示: 然后点中commit Directory后 打开终端进行项目根 ...

  2. 使用JAX-WS(JWS)发布WebService(一)

    JAX-WS概述: 通过Main发布一个简单WebService: JAX-WS(Java API for XML Web Services)规范是一组XML web services的JAVA AP ...

  3. 青岛Uber司机奖励政策(8月31号~9月6号)

    本周的奖励规则如下,请各位司机朋友按照自己的情况查询. 人民优步(People’s Uber) 滴滴快车单单2.5倍,注册地址:http://www.udache.com/如何注册Uber司机(全国版 ...

  4. 无法嵌入互操作类型“ADOX.CatalogClass”。请改用适用的接口。

    编译环境:vs2013 系统报错:无法嵌入互操作类型"ADOX.CatalogClass".请改用适用的接口. 解决方法:选中项目中引入的dll(本例中为Microsoft ADO ...

  5. 使用union

    QUERY: explain extended ) TRACE: { "steps": [ { "join_preparation": { "sele ...

  6. redux devtools调试工具

    项目安装: npm install redux-devtools-extension -dev 谷歌搜索 Redux DevTools 安装: 使用: 主要用到state&Dispatcher ...

  7. Selenium(Python) ddt读取MySQL数据驱动

    import unittestfrom time import sleep from ddt import ddt, datafrom pymysql import connectfrom selen ...

  8. Objective-C 内存管理和ARC

    内存管理 范围: 任何继承了NSObject的对象 对基本数据类型无效 原理: 每个对象内部都保存了一个与之相关联的整数 称为引用计数器 1.计数器的基本操作 当使用alloc new或者copy创建 ...

  9. Pyhton网络爬虫实例_豆瓣电影排行榜_Xpath方法爬取

    -----------------------------------------------------------学无止境------------------------------------- ...

  10. spring java config 初探

    Java Config 注解 spring java config作为同xml配置形式的另一种表达形式,使用的场景越来越多,在新版本的spring boot中 大量使用,今天我们来看下用到的主要注解有 ...