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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© LINUS 中级黑马   /  2013-4-11 00:08  /  1422 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 LINUS 于 2013-4-11 08:48 编辑

请教一下什么时候复写hashCode

与复写hashCode方法?请教一下equals方法的利用 与什么时候复写equals?

还有 对 comparable  comparator   compare   compareTo  之间的具体区别 比较疑惑

谢谢

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

5 个回复

倒序浏览
这就与集合联系了起来,当你需要将一个对象存入HashSet和HashMap中的时候,由于底层是哈希表数据结构,需要调用对象的hashCode和equals去判断元素是否相同,因为在set中不允许出现相同元素,当hashcode一致时,才调用equals。。你自己可以动手试试,。

comparable  //使元素自身具有比较性
compareTo //是上边这个接口需要实现的方法
comparator  //定义一个比较器
compare  //比较器中要实现的方法



具体的在我博客中

http://write.blog.csdn.net/postlist
回复 使用道具 举报

<P> import java.util.*;


class Student implements Comparable<Student>
/*

当一个对象被存入到集合中时,它可以被存入到List与Map中去。如果把他存入到TreeSet或者TreeMap等底层为二叉树结构的集合中时,
存入的元素必须要有有可比性!让元素实现可比性的两个方法:1 让存入的对象(例如本例中的Student类就是被存入集合中的元素)本身具有可比性,
即实现Comparable接口,2 在构造TreeSet或TreeMap时,传入比较器Comparator对象。

如果集合是ArrayList的话,Student类其实根本不用实现Comparable接口,因为ArrayList底层是数组结构,按照自己的编号排序。

如果集合是HashSet或者HashMap的话,Student类照样也不用实现Comparable接口,因为它们底层是Hash值,按照自身的Hash值进行排序。

让Student类实现Comparable接口的目的,其实只是为了避免Student类被存入到了二叉树结构的集合中。

在你这个代码中,最后将Students类存入到了HashMap中,其实完全可以不让Students实现Comparable接口。

*/

{

private String name;

private int age;


Student(String name,int age)

{

this.name=name;

this.age=age;

}

public int compareTo(Student s)
/*

这句话没什么意思。Students类实现了Comparable接口,就要复写Comparable接口中的comparTo方法。不理解的话可以看一下老毕的视频
,day07中有关于接口的详细讲解。你自己再查阅一下API文档java.lang.Comparable就能知道了。

*/

{

int num=new Integer(this.age).compareTo(new Integer(s.age));

/*

查看API文档,Comparable.compareTo()方法的返回值为int。这句话是什么意思呢?new Integer(this.age).compareTo(new Integer(s.age))
其实就是往集合中每存入一个Students类,就把存入的Students的age值与集合中已经存在的Students对象的age值相减!
如new Integer(3).compareTo(new Integer(2))=1,详见API文档java.lang.Integer的compareTo方法。

其实num的值完全也可以写作 this.age - s.age

*/


if(num==0)

/*

这句话是说,如果即将存入的Students的age值与集合中某一个Students类的age值相同,那么就让他们的另一个属性,即name属性进行比较。
使用的同样也是String类的compareTo方法。String类的compareTo方法是将字符串按字典顺序相减。如: "abc".compareTo("abb")=1

*/

return this.name.compareTo(s.name);


return num;

}


public int hashCode()

/*

这个是为了保证元素在存入到底层为Hash值的集合时不重复。HashSet和HashMap的底层都是Hash值结构,通过hash值来保证元素的唯一。

当Students对象被存入到HashSet或者HashMap中时, hm.put(new Student("lisi1",21),"beijing"),这时new Student("lisi1",21)作为一个匿名对象出现,
这个对象会有自己的一个Hash值(具体Hash值的算法我也不知道)。当你再往集合中存入new Student("lisi1",21)时,又会在内存中出现一个匿名对象,
他们的Hash值是不同的!所以,如果你的Students类不复写hashCode方法,这两个new Student("lisi1",21),"beijing")都会被存入进去!

但是当你复写了hashCode方法以后,这两个匿名对象都不会按照以前的那个方法计算hash值了,而是按照你给定的方法计算各自的hash值。

*/

{

return name.hashCode()+age*34;

/*

这个是指你想让Students类怎样计算自己的Hash值。默认Hash值的算法是很麻烦的,基本上new一个对象就有一个hash值。但是你自己手动复写了hash值算法,

让他们只比较姓名和年龄,这样的话hash值就会相同。例如:new Student("lisi1",21),如果按照默认的算法,hash值为11223344,当你再new一个Student("lisi1",21),

按照默认算法,hash值可能就变成了33445566。但是你的目的是想让姓名年龄相同视为同一个人,所以你就让他们的只比较姓名和年龄这两个元素就可以了。

age*34是为了Hash值偶然相同。比方说,"lisi"字符串的Hash值为40,年龄为20, 而"wangwu"字符串的hash值为32,年龄为28,name.hashCode()+age都等于60.

为了避免出现这样的情况,让就age随便乘以一个基数,那样 40+20*34就不再等于32+28*34了
*/

}


public boolean equals(Object obj)

/*

当Hash值相同时,才会调用equals方法对照内容进行比较。比方说,"lisi".hashCode()=40,age =20, "wangwu".hashCode()=720,age=0,

那么lisi.hashCode()+age*34正好等于 wangwu.hashCode()+age*34,但是这两个人却不是同一个人!所以此时就需要调用equals方法对内容进行比较!

*/

{

if(!(obj instanceof Student))

throw new ClassCastException("类型不匹配");


Student s=(Student)obj;


return this.name.equals(s.name) && this.age==s.age;
//对学生的姓名和年龄进行比较,如果返回为true,那就说明这个学生已经存入到了集合中,不会再存入,即集合中已经有了一个lisi,20,反之,则存入

}

public String getName()

{

return name;

}

public int getAge()

{

return age;

}

public String toString()

{

return name+".."+age;

}

}



class MapTest

{

public static void main(String[] args)
{

HashMap<Student,String> hm=new HashMap<Student,String>();


hm.put(new Student("lisi1",21),"beijing");

hm.put(new Student("lisi2",22),"shaghan");

hm.put(new Student("lisi3",23),"nanjing");

hm.put(new Student("lisi4",24),"wuhan");


//第一种取出方式 keySet


Set<Student> keySet=hm.keySet();


Iterator<Student> it=keySet.iterator();


while(it.hasNext())

{

Student stu=it.next();

String addr=hm.get(stu);

System.out.println(stu+".."+addr);

}

}

</P>
你这个问题当时我到这里的时候也看不懂.后来问了下大神.这是大神给我的..看完之后一下就通了.希望对你有帮助.
不知道这样有没有技术分

点评

必须有 哈哈  发表于 2013-4-11 00:38

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
孙百鑫 发表于 2013-4-11 00:37
import java.util.*;

谢谢啦······
回复 使用道具 举报
孙百鑫 发表于 2013-4-11 00:37
import java.util.*;

希望你可以把代码写入代码框中,如果不知道如何操作,请看这里吧:http://bbs.itheima.com/thread-42978-1-1.html

回复 使用道具 举报
如果问题未解决,请继续追问,如果没有问题了,请将帖子分类 改为“已解决”,谢谢
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马