Java中的HashCode(1)之hash算法基本原理


Java中的HashCode(1)之hash算法基本原理


2012-11-16 14:58:59     我来说两句  
   作者:woshixuye

收藏
   我要投稿


一、为什么要有Hash算法

Java
的集合有两类,一类是List,一类是Set。List内的元素是有序的,元素可以重复。Set元素无序,但元素不可重复。要想保证元素不重复,两个元素
是否重复应该依据什么来判断呢?用Object.equals方法。但若每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就
非常多了。也就是说若集合中已有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。于是
Java采用了哈希表的原理。哈希(Hash)是个人名,由于他提出哈希算法的概念就以他的名字命名了。

二、Hash算法原理

当Set接收一个元素时根据该对象的内存地址算出hashCode,看它属于哪一个区间,在这个区间里调用equeals方法。

确实提高了效率。但一个面临问题:若两个对象equals相等,但不在一个区间,根本没有机会进行比较,会被认为是不同的对象。所以Java对于eqauls方法和hashCode方法是这样规定的:

1 如果两个对象相同,那么它们的hashCode值一定要相同。也告诉我们重写equals方法,一定要重写hashCode方法。

2 如果两个对象的hashCode相同,它们并不一定相同,这里的对象相同指的是用eqauls方法比较。

三、例子

1 没有重写hashCode和equals的方法

package cn.xy.test;

public class Point1
{
  private int x;
  private int
y;

public Point1(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;

  }

}

public class HashSetAndHashCode
{
  public static void
main(String[] args)
  {
  HashSet<Point1> hs1 = new
HashSet<Point1>();
  Point1 p11 = new Point1(3, 3);
 
Point1 p12 = new Point1(3, 3);
  Point1 p13 = new Point1(3, 5);

  hs1.add(p11);
  hs1.add(p11);
  hs1.add(p12);
 
hs1.add(p13);
  System.out.println(hs1.size());
  }
}

答案是3

2 重写hashCode和equals的方法

package cn.xy.test;

public class Point2
{
  private int x;
  private int
y;

public Point2(int x, int y)
  {
  super();
 
this.x = x;
  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;
 
Point2 other = (Point2) obj;
  if (x != other.x) return false;

  if (y != other.y) return false;
  return true;
  }

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;

  }

}

public class HashSetAndHashCode
{
  public static void
main(String[] args)
  {
  HashSet<Point2> hs2 = new
HashSet<Point2>();
  Point2 p21 = new Point2(3, 3);
 
Point2 p22 = new Point2(3, 3);
  Point2 p23 = new Point2(3, 5);

  hs2.add(p21);
  hs2.add(p22);
  hs2.add(p23);
 
System.out.println(hs2.size());
  }
}

答案是2。p21和p22被认为是同一个对象。

3 没有重写hashCode的方法,但重写equals的方法

package cn.xy.test;

public class Point3
{
  private int x;
  private int
y;

public Point3(int x, int y)
  {
  super();
 
this.x = x;
  this.y = y;
  }

@Override
  public boolean equals(Object obj)
  {

  if (this == obj) return true;
  if (obj == null) return
false;
  if (getClass() != obj.getClass()) return false;
 
Point3 other = (Point3) obj;
  if (x != other.x) return false;

  if (y != other.y) return false;
  return true;
  }

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;

  }

}

public class HashSetAndHashCode
{
  public static void
main(String[] args)
  {
  HashSet<Point3> hs3 = new
HashSet<Point3>();
  Point3 p31 = new Point3(3, 3);
 
Point3 p32 = new Point3(3, 3);
  Point3 p33 = new Point3(3, 5);

  hs3.add(p31);
  hs3.add(p32);
  hs3.add(p33);
 
System.out.println(hs3.size());
  }
}

可能是2,可能是3。因为根据内存地址算出的hashcode不知道是否在一个区域。

Java中的HashCode(1)之hash算法基本原理

时间: 2024-08-03 15:33:44

Java中的HashCode(1)之hash算法基本原理的相关文章

千万不要误用 java 中的 HashCode 方法

刚才debug追堆栈的时候发现一个很奇怪的问题 我用IE8和Google的浏览器访问同一个地址 Action的 scope="session" 也设置了 而且两个浏览器提交的参数map也是互相独立的 不过很奇怪的一个 两个Action对象的hashmap是不同的但是它们的对象变量 paraterMap 的 哈希值 居然是一个 我大不解!( 找到原因以后发现这个问题其实只是一个好多年没有再提起的基础问题 ) 不过发现确实有朋友在网上说这个问题曾经引发过bug Java中的hashCode

java中的hashCode()方法

电话面试问到了HashMap里的类要实现什么方法,只知道是按哈希值查找所以查找效率很快,其它的一问三不知,现在来研究研究. 想研究研究,但是却不知道从哪里下手.... 汗!!!首先来咬文嚼字吧 什么是哈希值?百度了一下:哈希算法将任意长度的二进制值映射为固定长度的较小二进制值,这个小的二进制值称为哈希值.哈希值是一段数据唯一且极其紧凑的数值表示形式... 还是看不出和java类有什么关系...以前学数据结构时哈希表(也叫做散列表)这章还是很重要的,关键是那个哈希映射的哈希函数,也就是哈希算法,根

Java中Map相关的快速查找算法与唯一性(转载)

原文地址:http://blog.csdn.net/chuyuqing/article/details/19629229 在对<Set和hashCode()>的一篇原创文章写完后,由于对自己的一些论断产生了模糊和怀疑,因此又对Set进行了一些研究,形成本篇. 在Set的使用场景中,我们不外乎看中了她存储数据的唯一性,即不能存储重复值,这在某些应用场合下是很必要的一个特性.那么从更深一层来考虑,Set究竟如何使数据不重复的呢?从另一个层面来考虑,她又如何确保在验证数据是否重复过程中的快速性呢?假

浅谈Java中的hashCode方法

哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个方法的声明可知,该方法返回一个int类型的数值,并且是本地方法,因此在Object类中并没有给出具体的实现. 为何Object类需要这样一个方法?它有什么作用呢?今天我们就来具体探讨一下hashCode方法. 一.hashCode方法的作用 对于包含容器类型的程序设计语言来说,基本上都会涉及到has

java中的hashcode和euqals的区别和联系

一.equals方法的作用 1.默认情况(没有覆盖equals方法)下equals方法都是调用Object类的equals方法,而Object的equals方法主要用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象). 2 .要是类中覆盖了equals方法,那么就要根据具体的代码来确定equals方法的作用了,覆盖后一般都是通过对象的内容是否相等来判断对象是否相等. 没有覆盖equals方法代码如下: [java] view plaincopy //学生类 public class S

浅谈Java中的hashcode方法 - 海 子

浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个方法的声明可知,该方法返回一个int类型的数值,并且是本地方法,因此在Object类中并没有给出具体的实现. 为何Object类需要这样一个方法?它有什么作用呢?今天我们就来具体探讨一下hashCode方法. 一.hashCode方法的作用 对于包含容器类型的程

浅谈JAVA中的“hashcode()”方法

浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 为何Object类需要这样一个方法?它有什么作用呢?今天我们就来具体探讨一下hashCode方法. 根据这个方法的声明可知,该方法返回一个int类型的数值,并且是本地方法,因此在Object类中并没有给出具体的实现. 一.hashCode方法的作用 对于包含容器类型的程

浅谈Java中的hashcode方法(转载)

哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: 1 public native int hashCode(); 根据这个方法的声明可知,该方法返回一个int类型的数值,并且是本地方法,因此在Object类中并没有给出具体的实现. 为何Object类需要这样一个方法?它有什么作用呢?今天我们就来具体探讨一下hashCode方法. 一.hashCode方法的作用 对于包含容器类型的程序设计语言来说,基本上都会涉及到h

Java中的hashcode方法

一.hashCode方法的作用 对于包含容器类型的程序设计语言来说,基本上都会涉及到hashCode.在Java中也一样,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet.HashMap以及HashTable. 为什么这么说呢?考虑一种情况,当向集合中插入对象时,如何判别在集合中是否已经存在该对象了?(注意:集合中不允许重复的元素存在) 也许大多数人都会想到调用equals方法来逐个进行比较,这个方法确实可行.但是如果集合中已经存在一万条数据或