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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 李政 中级黑马   /  2012-9-13 12:00  /  4771 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 李政 于 2013-7-20 01:47 编辑

/*
举个例子,如果定义了一个学生类,并且重写了hash值,
并将学生类对象存入hashset集合中,那么应该是hash值小存入到集合的前面
编译下面的代码,发现是102 103 12 13,为什么?
hash值是怎么比较大小的呢
*/

import java.util.*;
class HashDemo
{
        public static void main(String[] args)
        {
                HashSet<Student> ts = new HashSet<Student>();
                ts.add(new Student(12));
                ts.add(new Student(13));
                ts.add(new Student(102));
                ts.add(new Student(103));
               
                Iterator<Student> it = ts.iterator();

                while(it.hasNext())
                {
                        Student s = it.next();
                        System.out.println("年龄:"+s.getAge());
                }
        }
}

class Student
{
private int age;
Student(int age)
{
        this.age = age;
}

public void setAge(int age)
        {
                this.age = age;
        }
public int getAge()
        {
                return age;
        }
public int hashCode()
        {
               
                return age;//返回年龄大小的hash值
        }
public boolean equals()
{
return false;
}

}


有了答案了:hashSet底层是哈希表,是用哈希表的规则来存放的。
至于哈希表的规则是什么,慢慢再了解




评分

参与人数 1技术分 +1 收起 理由
王德升 + 1

查看全部评分

7 个回复

倒序浏览
Set集合时无序的,你用hashCode个方法只是HashSet来判断元素是否是相同,API是这样的
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素这个说是HashSet是无序的。
回复 使用道具 举报
彭润生 发表于 2012-9-13 12:14
Set集合时无序的,你用hashCode个方法只是HashSet来判断元素是否是相同,API是这样的
此类实现 Set 接口, ...

不太明白你的意思
回复 使用道具 举报
彭润生 发表于 2012-9-13 12:14
Set集合时无序的,你用hashCode个方法只是HashSet来判断元素是否是相同,API是这样的
此类实现 Set 接口, ...

hashset集合元素存入的确是无序的,不知道你是不是这个意思。可是无序并不代表没有存入的规则,
回复 使用道具 举报
HashSet采用哈希算法存取对象集合,它内部采用对某个数字进行取余的方式对哈希码进行分组和划分对象区域。
回复 使用道具 举报
   HashSet通过hashCode和equals两个方法来保证元素的唯一性,是唯一性而不是顺序,能用方法排序的那个是TreeSet。
   楼主在这段代码中认为hashCode值的大小就是排序的顺序,显然不是这样的。
回复 使用道具 举报
李政 中级黑马 2012-9-13 14:35:42
7#
黑马张旭明 发表于 2012-9-13 13:46
HashSet通过hashCode和equals两个方法来保证元素的唯一性,是唯一性而不是顺序,能用方法排序的那个是Tr ...

代码中没有考虑hash值相同的情况,所有直接让equals返回flase了,写的时候忘了添加Objec类型参数。
:L
听毕老师讲课的时候说 hashset的集合中的排序是按照hash值从小到大排序的,所以就自己写了个代码,发现hash值不是按照十进制的大小来排的,所以就来请教各位前辈,hash值是怎么比较大小的
回复 使用道具 举报
返回set 的哈希码值。一个 set 的哈希码定义为此 set 中所有元素的哈希码和,其中 null 元素的哈希码定义为零。这就确保对于任意两个 set s1 和 s2 而言,s1.equals(s2) 就意味着 s1.hashCode()==s2.hashCode(),当然这是Set集合中的hashCode的比较。

对于一个普通的java类,如果编写者没有对Object类中的equals和hashcode方法进行覆盖的话,用的是Object类中的二者的实现,Object类中equals方法:
指示其他某个对象是否与此对象“相等”。 equals 方法在非空对象引用上实现相等关系:
     自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
     对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
     传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
     一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
     对于任何非空引用值 x,x.equals(null) 都应返回 false。
Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。
注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
而其hashcode的具体实现规则是:返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。
hashCode 的常规协定是:
在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
上述这些都是JavaAPI中的解释。
当然这只是Object类的实现,如果用户有自己的需求,可以对二者进行覆盖,编写自己的hashcode实现,比如根据自己定义的对象中的属性信息来实现,比如楼主编写的Student类中hashcode是通过该类的属性age的大小来判断。




回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马