请问高手:
1. hashcode()是干什么用的?
2. 如果我实现了comparable接口,重写了equals(),为什么还要重写hashCode()呢?默认的equals()是比的hashCode吗?hashCode是基于内存地址计算出来的,可是一个类的两个实例是放在堆区不同的地址空间的,为什么计算出的hash码还是一样的呢?
3. comparable接口里的compareTo()就是用于供系统回调实现自定义排序的吗?那Comparator接口中的compare()呢?它们的异同?系统什么时侯会回调comparare方法呢?看JDK看的我云里雾里的。百思不得其解,还望哪位好心人能指点一二,在此跪谢了!
1. hashcode()是干什么用的?
2. 如果我实现了comparable接口,重写了equals(),为什么还要重写hashCode()呢?默认的equals()是比的hashCode吗?hashCode是基于内存地址计算出来的,可是一个类的两个实例是放在堆区不同的地址空间的,为什么计算出的hash码还是一样的呢?
3. comparable接口里的compareTo()就是用于供系统回调实现自定义排序的吗?那Comparator接口中的compare()呢?它们的异同?系统什么时侯会回调comparare方法呢?看JDK看的我云里雾里的。百思不得其解,还望哪位好心人能指点一二,在此跪谢了!
解决方案 »
- FutureTask返回值问题
- getClass().getClassLoader() 返回 null
- 错误出在哪里?一个Struts的应用中出现的问题
- 对象和实例有什么区别?Class c =Class.forName("ss.dd.bb.Bean");和Bean b = new Bean();有什么区别?
- 关于 JDK1.3.1_08\j2sdk-1_3_1_08-solaris-sparc.sh
- 怎样写这个方法???
- [讨论]内部类的加载问题
- Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver")老出错,晕
- 请求帮助,使用可更新ResultSet更新含中文字符的字段时出现异常
- 哪位大虾知道怎样做一个报表编辑器,或提供一些相关的资料,高分相赠!
- 求教用Java实现网站数据采集方案?
- String split正则表达式的问题
在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。
以下情况不 是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。) 当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
全部粘贴中文API里的原文有用吗?
就是看文档,不太理解才问的!你有全给人家粘贴一遍!
例如内存中有这样的位置
0 1 2 3 4 5 6 7
而我有个类,这个类有个字段叫ID,我要把这个类存放在以上8个位置之一,如果不用hashcode而任意存放,那么当查找时就需要到这八个位置里挨个去找,或者用二分法一类的算法。
但如果用hashcode那就会使效率提高很多。
我们这个类中有个字段叫ID,那么我们就定义我们的hashcode为ID%8,然后把我们的类存放在取得得余数那个位置。比如我们的ID为9,9除8的余数为1,那么我们就把该类存在1这个位置,如果ID是13,求得的余数是5,那么我们就把该类放在5这个位置。这样,以后在查找该类时就可以通过ID除8求余数直接找到存放的位置了。2.但是如果两个类有相同的hashcode怎么办那(我们假设上面的类的ID不是唯一的),例如9除以8和17除以8的余数都是1,那么这是不是合法的,回答是:可以这样。那么如何判断呢?在这个时候就需要定义 equals了。
也就是说,我们先通过 hashcode来判断两个类是否存放某个桶里,但这个桶里可能有很多类,那么我们就需要再通过 equals 来在这个桶里找到我们要的类。
那么。重写了equals(),为什么还要重写hashCode()呢?
想想,你要在一个桶里找东西,你必须先要找到这个桶啊,你不通过重写hashcode()来找到桶,光重写equals()有什么用啊
3。你要对A类排序,有两种方法,一种就是让A类实现comparabole结构并实现compareTo()方法,那么可以通过Collections.sort(List<A> list)对其进行排序
另一种方法:自己定义一个类B实现Comparator类并实现compare方法,
然后通过Collections.sort(List<A> list,B b)进行排序
例如内存中有这样的位置
0 1 2 3 4 5 6 7
而我有个类,这个类有个字段叫ID,我要把这个类存放在以上8个位置之一,如果不用hashcode而任意存放,那么当查找时就需要到这八个位置里挨个去找,或者用二分法一类的算法。
但如果用hashcode那就会使效率提高很多。
我们这个类中有个字段叫ID,那么我们就定义我们的hashcode为ID%8,然后把我们的类存放在取得得余数那个位置。比如我们的ID为9,9除8的余数为1,那么我们就把该类存在1这个位置,如果ID是13,求得的余数是5,那么我们就把该类放在5这个位置。这样,以后在查找该类时就可以通过ID除8求余数直接找到存放的位置了。2.但是如果两个类有相同的hashcode怎么办那(我们假设上面的类的ID不是唯一的),例如9除以8和17除以8的余数都是1,那么这是不是合法的,回答是:可以这样。那么如何判断呢?在这个时候就需要定义 equals了。
也就是说,我们先通过 hashcode来判断两个类是否存放某个桶里,但这个桶里可能有很多类,那么我们就需要再通过 equals 来在这个桶里找到我们要的类。
那么。重写了equals(),为什么还要重写hashCode()呢?
想想,你要在一个桶里找东西,你必须先要找到这个桶啊,你不通过重写hashcode()来找到桶,光重写equals()有什么用啊
3。你要对A类排序,有两种方法,一种就是让A类实现comparabole结构并实现compareTo()方法,那么可以通过Collections.sort(List<A> list)对其进行排序
另一种方法:自己定义一个类B实现Comparator类并实现compare方法,
然后通过Collections.sort(List<A> list,B b)进行排序
例如内存中有这样的位置
0 1 2 3 4 5 6 7
而我有个类,这个类有个字段叫ID,我要把这个类存放在以上8个位置之一,如果不用hashcode而任意存放,那么当查找时就需要到这八个位置里挨个去找,或者用二分法一类的算法。
但如果用hashcode那就会使效率提高很多。
我们这个类中有个字段叫ID,那么我们就定义我们的hashcode为ID%8,然后把我们的类存放在取得得余数那个位置。比如我们的ID为9,9除8的余数为1,那么我们就把该类存在1这个位置,如果ID是13,求得的余数是5,那么我们就把该类放在5这个位置。这样,以后在查找该类时就可以通过ID除8求余数直接找到存放的位置了。2.但是如果两个类有相同的hashcode怎么办那(我们假设上面的类的ID不是唯一的),例如9除以8和17除以8的余数都是1,那么这是不是合法的,回答是:可以这样。那么如何判断呢?在这个时候就需要定义 equals了。
也就是说,我们先通过 hashcode来判断两个类是否存放某个桶里,但这个桶里可能有很多类,那么我们就需要再通过 equals 来在这个桶里找到我们要的类。
那么。重写了equals(),为什么还要重写hashCode()呢?
想想,你要在一个桶里找东西,你必须先要找到这个桶啊,你不通过重写hashcode()来找到桶,光重写equals()有什么用啊
3。你要对A类排序,有两种方法,一种就是让A类实现comparabole结构并实现compareTo()方法,那么可以通过Collections.sort(List<A> list)对其进行排序
另一种方法:自己定义一个类B实现Comparator类并实现compare方法,
然后通过Collections.sort(List<A> list,B b)进行排序
import java.util.*;
class A
{
private int i;
public A(int i){
this.i = i;
}
public String toString(){
return " "+i;
}
public boolean equals(Object o){
A a = (A)o;
return (a.i==i) ? true : false ;
}
public int hashCode(){
return i;
}
}public class TestA
{
public static void main(String[] args){
HashSet set = new HashSet();
for(int i = 0;i<=3;i++)
set.add(new A(i));
System.out.println(set);
set.add(new A(1));
System.out.println(set);
System.out.println(set.contains(new A(0)));
System.out.println(set.add(new A(1)));
System.out.println(set.add(new A(4)));
System.out.println(set);
}}
你分别注释掉hashCode()和 equals()来比较一下他们作用就可以拉,关键要自己动手看看比较的结果你就可以记得很清楚啦comparable接口作用是使得对象天生就具有比较的功能,它是为了支持Arrays.sort(Object[], Comparator),TreeSet,TreeMap 这样集合类而存在的,这些就需要你自己去查文档拉 注意的是TreeSet,TreeMap 确定存入的对象是否重复时 用的不是equals() 而是comparable的 compareTo(T o) 方法 。
Comparator接口是一个比较器,他的作用与comparable 的作用差不多,不过他是通过参数传递来实现的 象 : TreeSet 的构造器中不是有这么一个方法吗: public TreeSet(Comparator<? super E> c),你自己去查查看,确定存入的对象是否重复时用的就是 int compare(T o1,T o2);
系统什么时侯会回调comparare方法呢?你去看看 Arrays 中的sort 方法就知道啦 !!!!
import java.util.*;
class A
{
private int i;
public A(int i){
this.i = i;
}
public String toString(){
return " "+i;
}
public boolean equals(Object o){
A a = (A)o;
return (a.i==i) ? true : false ;
}
public int hashCode(){
return i;
}
}public class TestA
{
public static void main(String[] args){
HashSet set = new HashSet();
for(int i = 0;i<=3;i++)
set.add(new A(i));
System.out.println(set);
set.add(new A(1));
System.out.println(set);
System.out.println(set.contains(new A(0)));
System.out.println(set.add(new A(1)));
System.out.println(set.add(new A(4)));
System.out.println(set);
}}
你分别注释掉hashCode()和 equals()来比较一下他们作用就可以拉,关键要自己动手看看比较的结果你就可以记得很清楚啦comparable接口作用是使得对象天生就具有比较的功能,它是为了支持Arrays.sort(Object[], Comparator),TreeSet,TreeMap 这样集合类而存在的,这些就需要你自己去查文档拉 注意的是TreeSet,TreeMap 确定存入的对象是否重复时 用的不是equals() 而是comparable的 compareTo(T o) 方法 。
Comparator接口是一个比较器,他的作用与comparable 的作用差不多,不过他是通过参数传递来实现的 象 : TreeSet 的构造器中不是有这么一个方法吗: public TreeSet(Comparator<? super E> c),你自己去查查看,确定存入的对象是否重复时用的就是 int compare(T o1,T o2);
系统什么时侯会回调comparare方法呢?你去看看 Arrays 中的sort 方法就知道啦 !!!!
import java.util.*;
class A
{
private int i;
public A(int i){
this.i = i;
}
public String toString(){
return " "+i;
}
public boolean equals(Object o){
A a = (A)o;
return (a.i==i) ? true : false ;
}
public int hashCode(){
return i;
}
}public class TestA
{
public static void main(String[] args){
HashSet set = new HashSet();
for(int i = 0;i<=3;i++)
set.add(new A(i));
System.out.println(set);
set.add(new A(1));
System.out.println(set);
System.out.println(set.contains(new A(0)));
System.out.println(set.add(new A(1)));
System.out.println(set.add(new A(4)));
System.out.println(set);
}}
你分别注释掉hashCode()和 equals()来比较一下他们作用就可以拉,关键要自己动手看看比较的结果你就可以记得很清楚啦
hashcode和equals是帮定关系,一般不常用.
1. equals()在比较除8大包装类和String类外,比的是引用,在比较这9个类时,
比的不是引用,而是转换为相应的基本类型来比的(除了String-->char[]).
(顺便问一下:为什么StringBuffer没有重写equals()?)下面是我的理解:
如果没重写equals(),则对象之间比较时会按内存地址比,这样任何类的任何实例都不可能
equals()返回true了.
如果重写了equals()则是用自己定义的方法来比较了.这时即使不重写hashCode()也能
得出正确的比较结果,但这时返回的hashCode就不一样了(一样的可能性非常小),如果只想
比较不干点别的(弄着好玩的),这时hashCode对我们来说并不重要,但是:正如楼上的朋友所说:当要用到散列数据结构来存储和取出数据时,全是通过hashCode来操作的,如果哈希码不一样就不用equal()了,如果哈希码一样再equals()比.如果重写了equals()而没重写hashCode()则会导致equals()为true,但是Set里还会有两个或多个这类对象的引用(因为hashCode不一样).另一个极端情况:
只重写hashCode()但不重写equals(),会导致同一个类的多个相同实例的引用被加到Set里,不同类的实例反倒可能加不进来,因为hashCode一样(虽然机率狂小).
(再顺便问一下:JAVA中是如何计算一个对象的hash码的,不是按内存地址计算的吗?内存地址是唯一的,为什么还可能会出现重复的hash码呢?)
不知道偶的理解对不对?还请高手们指点指点小弟.2. Comparator 接口中的compare方法产生一个比较器,这个比较器的比较级别高于在Comparable接口中重写的compareTo(),这样理解对吗?再次跪谢!!
(1)当obj1.equals(obj2)为true时obj1.hashCode() == obj2.hashCode()必须为true
(2)当obj1.hashCode() != obj2.hashCode()为true时obj.equals(obj2)必须为true2.一个类实现Comparable接口是用来决定该类对象的自然顺序,这样把该类对象放入TreeSet,TreeMap,时会根据该类对象的自然顺序自动进行排序,另外往Queue里面存的时候也会根据对象自然顺序排序3.光实现Comparable只能决定该类对象自然顺序,但是很多时候需要自定义排序规则,那么就要实现
Comparator接口,例如一个People实现了Comparable接口并且定义自然顺序为按照名字字母顺序排序,那么把People存到List里面的时候可以用Collections.sort()方法根据自然顺序对该List进行排序,问题就在于我现在要把People按照年龄排序该怎么办呢?一个类实现了Comparable只能重写compareTo()方法一次,那么也只能有一种顺序--自然顺序,但是为了可以用age大小排序这个List的话,就必须使用一个类实现Comparator并且重写compare()方法,定义按照age排序的规则,然后调用Collections 的 static <T> void sort(List<T> list, Comparator<? super T> c) 这个方法来按照指定比较器规定的顺序来对List排序
(1)当obj1.equals(obj2)为true时obj1.hashCode() == obj2.hashCode()必须为true
(2)当obj1.hashCode() == obj2.hashCode()为false时obj.equals(obj2)必须为false