A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© hel 中级黑马   /  2013-11-8 02:16  /  1089 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

hashcode方法对于HashSet的作用是什么?

评分

参与人数 1技术分 +1 收起 理由
黄炳期 + 1

查看全部评分

4 个回复

倒序浏览
hashCode
当使用toString方法的时候返回一个 "类型名@#$%#^%$ "的东西,比如一个****@4e57de。"@ "前面的是你的类名,后面的就是散列码的16进制表示。

hashCode 叫哈希代码或称散列码,简单的说就是通过哈希算法算出来的一大窜数字之类的东西和内存有关。默认的实现是将对象内部地址转化为整数作为HashCode,这当然能保证每个对象具有不同的HasCode,因为不同的对象内部地址肯定不同(废话)。因此你可以简单理解为对象在内存中的地址 担不是绝对物理地址。

hashSet
他是一个集合,Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复
当我们向HashSet集合中添加元素时,它是按hash算法来存储集合中的元素。首先HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该hashCode值决定该对象在HashSet中的存储位置。如果两个元素通过equals方法比较返回true,但它们的hashCode()方法返回值不相等,HashSet将会把它们存储在不同位置,也就添加成功。
HashSet集合判断两个元素的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值也相等

评分

参与人数 1技术分 +1 收起 理由
黄炳期 + 1

查看全部评分

回复 使用道具 举报
在存放集合这种数据的时候,我们可以选择List和Set两种形式,当然,Java当中它们不是具体的实现类.我们可以使用具体的实现类进行数据的存储.
但是List和Set的最显著区别,应该是,List可以放置相同的元素,Set只能放置不同的元素.也就是说Set里面的元素具有唯一性.

当然ArrayList和LinkedList也只是具体的实现形式不同了.我们也可以实现一个ArraySet或LinkedSet.但是.我们会发现一个比较严重的问题.就是.当我们向ArraySet(或LinkedSet)里面添加元素的时候,我们要逐个比较里面的所有已有元素.这样,当集合中数量非常多的时候,比较次数也会直线上升.也就是说,当我们结合中有10000个元素的时候,我再添加一个元素,要首先比较最多10000次才能确定我要添加的元素是否已经存在了,这会严重影响集合的性能.

为了更快捷的检索数据,我们才引进了hashCode的概念,每个Set里面的元素都会有一个hashCode的值,我们可以按照hashCode的值来存储集合里面的元素.如果要检索集合里面是否存在要添加的元素,只要先将该元素的hashCode值算出来,再到相应的位置进行查找,就可以了.对于相同hashCode的不同元素,我们把这个位置,按照链表的形式进行存放.这样,就可以很大程度上减少比较的次数.举个例子:

我们Set集合里面可能已经10000个不同的元素了.当添加新元素的时候,我们根据新元素的hashCode值,找到相应的位置,这个位置所对应的链表里面,可能只有五个元素,那么,我们只要比较5次,就可以判断整个集合中是否已经存在该元素了,因为,相同元素的hashCode一定是相同的.呵呵.为了使根据hashCode确定位置的速度更快,我们采用数组的下标来表示位置,数组里面存放链表.下标都是自然数,所以,要把hashCode进行向数组下标的映射转换(其实就是与运算).

最后,来谈谈,什么情况下重写hashCode,我们知道,自然情况下,hashCode所产生的值是很有规律的,这样的话,拥有10000个元素的Set,可能有9000个都在同一个位置上,这样,再加一个相同hashCode的元素时,那可能要比较90000次了.所以,我们要自己定义hashCode使得这些元素的hashCode在hashSet里面存储更加分散.不过Java的HashSet里面,已经有一个方法,将元素的hashCode做打散处理了,这个方法对于默认的hashCode还是比较有效果的.对于熟悉这些内容的程序员,为了程序的效率更高,可以重写hashCode方法.但是,不能使用随机数充当hashCode,每个元素,都应该对应唯一的一个hashCode,一个hashCode可以对应多个元素.

也可以这么说,只要对象内容一样,我们就有必要重写它的hashCode,hashCode代表的是对象的内存地址,或者说内存地址根据这个hash码得到, 一般的集合都重写了hashCode方法,而当我们自定义对象的时候就要重写hasdCode方法,保证内容一样的对象算出相同的hash码。hash码的用处只体现在需要散列的地方,如hashSet、hashMap,提高用户查找速度
回复 使用道具 举报
hel 中级黑马 2013-11-10 20:01:48
板凳
HashSet集合里面的元素都是没有索引的,实际上当程序向HashSet集合中添加元素的时候,HashSet集合会根据这个元素的HashCode值来决定他的存储位置--这个就是说,每个元素的hashCode就是他的"索引";
为什么不直接使用数组呢,还需要使用HashSet呢?,因为数组元素的索引是连续的 ,而且数组的长度是固定的,无法自由增加数组的长度,而且HashSet就不一样了,HashSet来根据每个元素HashCode作为索引,从而自由增加了HashSet的长度,并可以根据元素的HashCode值来访问元素,所以,从HashSet中访问元素的时候,HashSet先计算元素的HashCode值(也就是调用这个对象的HashCode()方法的返回值),安徽直接到这个HashCode对于的位置去取出这个元素---这就是HashSet集合速度很快的原因
回复 使用道具 举报
hashCode
当使用toString方法的时候返回一个 "类型名@#$%#^%$ "的东西,比如一个****@4e57de。"@ "前面的是你的类名,后面的就是散列码的16进制表示。

hashCode 叫哈希代码或称散列码,简单的说就是通过哈希算法算出来的一大窜数字之类的东西和内存有关。默认的实现是将对象内部地址转化为整数作为HashCode,这当然能保证每个对象具有不同的HasCode,因为不同的对象内部地址肯定不同(废话)。因此你可以简单理解为对象在内存中的地址 担不是绝对物理地址。

hashSet
他是一个集合,Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复
当我们向HashSet集合中添加元素时,它是按hash算法来存储集合中的元素。首先HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该hashCode值决定该对象在HashSet中的存储位置。如果两个元素通过equals方法比较返回true,但它们的hashCode()方法返回值不相等,HashSet将会把它们存储在不同位置,也就添加成功。
HashSet集合判断两个元素的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值也相等

总结hashCode方法对于hashSet的作用
表面上看来,HashSet集合里面的元素都是没有索引的,实际上当程序向HashSet集合中添加元素的时候,HashSet集合会根据这个元素的HashCode值来决定他的存储位置--这个就是说,每个元素的hashCode就是他的"索引";
为什么不直接使用数组呢,还需要使用HashSet呢?,因为数组元素的索引是连续的 ,而且数组的长度是固定的,无法自由增加数组的长度,而且HashSet就不一样了,HashSet来根据每个元素HashCode作为索引,从而自由增加了HashSet的长度,并可以根据元素的HashCode值来访问元素,所以,从HashSet中访问元素的时候,HashSet先计算元素的HashCode值(也就是调用这个对象的HashCode()方法的返回值),安徽直接到这个HashCode对于的位置去取出这个元素---这就是HashSet集合速度很快的原因

如下一个例子;[code=java]package cn.itcast.zhanjc;


import java.util.*;
/**
*
*/

//类A的equals方法总是返回true,但没有重写其hashCode()方法
class A
{
public boolean equals(Object obj)
{
return true;
}
}
//类B的hashCode()方法总是返回1,但没有重写其equals()方法
class B
{
public int hashCode()
{
return 1;
}
}
//类C的hashCode()方法总是返回2,但没有重写其equals()方法
class C
{
public int hashCode()
{
return 2;
}
public boolean equals(Object obj)
{
return true;
}
}
public class HashCode
{
public static void main(String[] args)
{
HashSet books = new HashSet();
//分别向books集合中添加2个A对象,2个B对象,2个C对象
books.add(new A());
books.add(new A());
books.add(new B());
books.add(new B());
books.add(new C());
books.add(new C());
System.out.println(books);
}
}[/code]结果为[code=java][cn.itcast.zhanjc.B@1, cn.itcast.zhanjc.B@1, cn.itcast.zhanjc.C@2, cn.itcast.zhanjc.A@1fb8ee3, cn.itcast.zhanjc.A@c17164][/code]
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马