黑马程序员技术交流社区

标题: 关于compare [打印本页]

作者: 何创    时间: 2013-1-22 12:36
标题: 关于compare
本帖最后由 张向辉 于 2013-1-23 09:41 编辑

class student implements comparable
{
   //学生属性
}
public void equals()
{
//相关代码
}
public int hashcode()
{
//相关代码
}
看视频里面 为什么每次只要使用学生类的时候都要进行 hashcode 和equals 两个方法、、如果说学生没有比较性,直接继承comparable接口 复写comparto 方法不就行了
为什么还要复写那些方法。
我查阅API发现comparto方法是这样的:
compareto (参数1,参数2)
{
}
可是视频里面的comparto方法只是用了一个参数,,我也尝试过  但是总是强制我传入两个参数。。
求解。。最好能提供一些相关student代码 。。谢谢了,非常感谢。
作者: 偏執旳、靑春    时间: 2013-1-22 12:40
哪一集视频 我去看看!突然也忘记了
作者: 小学生0987    时间: 2013-1-22 13:46
因为比较时就是调用那两个方法进行比较的,还有comparable接口的compareto方法就是一个参数啊
作者: 何创    时间: 2013-1-22 13:49
小学生0987 发表于 2013-1-22 13:46
因为比较时就是调用那两个方法进行比较的,还有comparable接口的compareto方法就是一个参数啊 ...

唉。。求本质答案啊。。
作者: 王溢君    时间: 2013-1-22 14:20
复写equal和hashCode是为了能放进hash类型的集合中,比如hashset,,,复写compareTo方法是为了让学生能放进去二叉树数据集合中。比如treeSet!!!直接实现comparable接口 ,此是实现,不是继承。复写comparTo大写T!这个后面只有一个参数。。。。。。。。。另外一种比较器是Comparator复写compare方法。这个方法才是二个参数。我想你是搞混了吧?
作者: 何创    时间: 2013-1-22 14:42
luck28 发表于 2013-1-22 14:20
复写equal和hashCode是为了能放进hash类型的集合中,比如hashset,,,复写compareTo方法是为了让学生能放进去 ...

那 每个对象都有自己的hashcode,student对象也有他们的hashcode,为什么要复写,目的意图又是什么呢???用自己的不行吗??为不能用自己的什么啊??那复写equal的目的 意图 又到底是什么呢、?
作者: 蒋争辉    时间: 2013-1-22 14:50
这里涉及到数据结构的知识,因为所有的类都继承自Object,在哈希表对象比较时JVM会自动调用对象的equal方法,就student这个对象来说,本身是不具备比较性的。但是我们认为定义他的属性,比如 age、name这两个属性,当两个学生对象stu1和stu2的这两个属性都相同时,我们认为这两个学生对象才是同一个对象。当我们需要让student对象具备比较性的时候,我们有2种方法:1 重写equal方法和hashCode方法  2 实现comparable接口,然后实现compareTo方法。在毕老师视频中讲的很详细。代码我就不贴了,实在不清楚运行原理,自己可以在复写的方法中打印相关属性方便比较。
作者: 黑马张英涛    时间: 2013-1-22 15:06
class Student {
        public String name;
        public int age;
        public Student(String name, int age) {
                this.name = name;
                this.age = age;
        }
}
对于一个学生"张三",我们用他生成了两个对象:
Student s1=new Student("张三",20);   Student s2=new Student("张三",20);
我们怎么判断他们是否是一个对象呢?如果直接使用"=="或equals()方法进行比较的话
System.out.println(s1==s2);
System.out.println(s1.equals(s2));
那么结果都是 false 。因为如果Student不复写equals()方法,那么s1.equals(s2)实际上调用的是Object类的equals()方法,
查看他的源代码可以发现该方法实际上返回的就是s1==s2,所以我们要重写equals()方法。
        public boolean equals(Object obj) {
                if(!(obj instanceof Student))
                        return false;
                Student s=(Student)obj;
                return this.name==s.name && this.age==s.age;
        }

至于复写hashCode(),是因为默认的话哈希值是根据地址计算来的,如果不复写的话,那么我们认为s1跟s2是同一个对象,
但是他们在内存中存放的位置不同却导致了不同的哈希值,这在进行哈希类集合操作时将产生严重问题。
实现Comparable接口是为了能将对象放到二叉树类的集合中(典型的treeSet),这类集合有自动排序的功能,
他就是靠调用对象的compareTo() 方法。




作者: 何创    时间: 2013-1-22 15:06
java—jiang 发表于 2013-1-22 14:50
这里涉及到数据结构的知识,因为所有的类都继承自Object,在哈希表对象比较时JVM会自动调用对象的equal方法 ...

那重写equals和hashcode的目的为什么?为了让他们对象的hashcode相同吗??stu1和stu2都有自己的hashcode为什么不能拿它们自身的值来进行比较??你说呢?
作者: 蒋争辉    时间: 2013-1-22 15:10
何创 发表于 2013-1-22 15:06
那重写equals和hashcode的目的为什么?为了让他们对象的hashcode相同吗??stu1和stu2都有自己的hashcode ...

重写就是为了比较student对象的各自属性值(这里是age和name),hashCode不同对象就被视作不同的对象,对于hashSet、treeSet结果在存放对象的时候都会对对象进行比较,确保不重复。
stu1和stu2都有自己的hashcode 这句话是不准确的,准确的说应该是student的hashCode方法。
作者: 何创    时间: 2013-1-22 15:14
黑马张英涛 发表于 2013-1-22 15:06
class Student {
        public String name;
        public int age;

谢谢、你的意思就是说 如果判断两个对象具有比较性第一要复写equals 并且复写hashcode 同时进行复写,对么?
作者: 黑马张英涛    时间: 2013-1-22 15:19
何创 发表于 2013-1-22 15:14
谢谢、你的意思就是说 如果判断两个对象具有比较性第一要复写equals 并且复写hashcode 同时进行复写,对 ...

对,如果想要自己定义的类有比较好的健壮性最好3个方法全都用自己的方法覆盖或实现
作者: 舒远    时间: 2013-1-23 09:29
原则:两对象比较,如果通过equals比较相等,则应该让他们的hashCode()也相等。
所以一般自定义类复写equals方法同时也要复写hashCode()方法。但不是绝对的
这种同时复写的情况多见于你将这个类的对象需要放进HashSet或者HashMap之类的通过Hash算法存放数据的数据结构中,才适用这个原则。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2