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