JAVA学习之HashCode
public native int hashCode();
返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable
提供的哈希表)的性能。
一、HashCode的作用
我们通常会用equals判断集合中是否包含一个对象,这种方式需要遍历集合中每一个元素,然后对他们一一进行equals方法比较。对于少量数据的集合该方式自然可以,但当我们的数据很多例如一万个,如果还使用这种逐个遍历的方式显然不合适。于是有人发明了一种哈希算法来提高从集合中查找元素的效率。这种方式的核心就是将集合分为若干个区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,查找对象时我们先根据对象的哈希码来确定该对象存储在某个区域。然后在这个区域内查找元素。
在java中HashSet、HashMap以及HashTable这些散列集合,就是与hashCode方法一起使用。
下面这段代码是java.util.HashMap的中put方法的具体实现:
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
} modCount++;
addEntry(hash, key, value, i);
return null;
}
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演示:
package com.jalja.org.base.test; import java.util.HashSet;
import java.util.Set; public class Point {
private int x;
private int y; public Point(int x, int y) {
super();
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 int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Point other = (Point) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
public static void main(String[] args) {
Point point1=new Point(1,2);
Point point2=new Point(2,3);
Point point3=new Point(3,4);
Set<Point> set=new HashSet<Point>();
set.add(point1);
set.add(point2);
set.add(point3);
System.out.println(set.size());//
point1.setX(5);//改变 point1的x值
set.remove(point1);//移除 point1
System.out.println(set.size());//
}
}
从结果可以看出 point1已经无法删除了。
JAVA学习之HashCode的更多相关文章
- 0025 Java学习笔记-面向对象-final修饰符、不可变类
final关键字可以用于何处 修饰类:该类不可被继承 修饰变量:该变量一经初始化就不能被重新赋值,即使该值跟初始化的值相同或者指向同一个对象,也不可以 类变量: 实例变量: 形参: 注意可以修饰形参 ...
- 《Java学习笔记(第8版)》学习指导
<Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...
- JAVA学习第三十六课(经常使用对象API)— Set集合:HashSet集合演示
随着Java学习的深入,感觉大一时搞了一年的ACM,简直是明智之举,Java里非常多数据结构.算法类的东西,理解起来就轻松多了 Set集合下有两大子类开发经常使用 HashSet集合 .TreeSet ...
- 201521123105 第四周Java学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 继承与多态的概念与实现父类与之类的关系解决代码复用的办法 2. 书面作业 2.1 将在网上商 ...
- java学习(三)
学号 20189214 <Java程序设计>第三周学习总结 教材学习内容总结 核心类 java.lang.Object 所有的类都直接派生自这个类. java.lang.String St ...
- Java 基础:hashCode方法
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 一.前言 泥瓦匠最近被项目搞的天昏地暗.发现有些要给自己一些目标,关于技术的目标: 专注很重要.专注J ...
- Java学习:注解,反射,动态编译
狂神声明 : 文章均为自己的学习笔记 , 转载一定注明出处 ; 编辑不易 , 防君子不防小人~共勉 ! Java学习:注解,反射,动态编译 Annotation 注解 什么是注解 ? Annotat ...
- Java学习个人总结
声明:个人原创,转载请在文章开头明显位置注明出处:https://www.cnblogs.com/sunshine5683/p/10063960.html 学习从来都是一个阶段的学习,然后进行整理与总 ...
- java学习笔记13--反射机制与动态代理
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...
随机推荐
- python教程(二)·条件语句
条件语句一般用来判断给定的条件是否成立,根据结果来执行不同的代码,也就是说,有了条件语句,才可以根据不同的情况做不同的事,从而控制程序的流程. 布尔类型 前面说到数据类型的时候,其中有一种叫 &quo ...
- cannot import name '_imaging' 报错
例子如下: from PIL import Image import pytesseract as pt text = pt.image_to_string(Image.open("text ...
- 20145202马超《网络对抗》Exp7 网络欺诈技术防范
本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法.具体有(1)简单应用SET工具建立冒名网站(2)ettercap DNS spoof(3)结合应用两种技术,用DNS spo ...
- Nodejs中的流
Nodejs中的很多地方都用到了流,流是一个很常见的概念,一个http请求,控制台输入输出的形式都是流.流可以分为三种: 可读流 可写流 既能读又能写 其中第三种流又可以分为全双工流Duplex和转换 ...
- Android7.0 应用内升级
Android7.0应用内升级 最近线上项目在7.0机器上出现应用内升级失败,原来是由于Android7.0权限问题导致. 如果项目的 targetSdkVersion>=24 在处理应用内升级 ...
- centos配置ip地址 添加多个ip地址的方法
操作如下,登陆SSH: vi /etc/sysconfig/network-scripts/ifcfg-eth0: 第二个IP,就是 vi /etc/sysconfig/network-scripts ...
- Putty远程连接Ubuntu14.04
步骤一.在ubuntu系统中安装ssh,可使用如下的命令进行安装: sudo apt-get install openssh-server 步骤二.为了保险起见,安装完成后重启一下ssh服务,命令如下 ...
- Qt-QML-Slider-滑块-Style
感觉滑块这个东西,可以算是一个基本模块了,在我的项目中也有这个模块,今天我将学一下一下滑块的使用以及美化工作. 想学习滑块,那就要先建立一个滑块,新建工程什么的这里就省略了,不会的可以看我前面的几篇文 ...
- Python拼接字符串的7种方法
1.直接通过+操作: s = 'Python'+','+'你好'+'!'print(s) 打印结果: Python,你好! 2.通过join()方法拼接: 将列表转换成字符串 strlist=['Py ...
- lintcode First Unique Number In Stream
First Unique Number In Stream 描述: Given a continuous stream of numbers, write a function that return ...