java面试题3

1.说一说你对 java.lang.Object 对象中 hashCode 和 equals 方法的理解。在什么场景下需要重新实现这两个方法

两个方法是一起的,equals方法对比两个对象是否值相等,如果相等他们的hashcode也要相等,如果如果你有需要要重写equals方法,也要重写hashCode方法(自己理解,(⊙﹏⊙))

object的默认实现为equals为:x == y,hashCode为对象的内存地址转换成的整数 
public native int hashCode();//代表对象的特征
public boolean equals(Object obj) {//代表对象的比较
    return (this == obj);
}

其中Object中若两个引用的equals()相等,那么两个对象的的hashCode()一定相同,

对于重写Object的类的equals()和hashCode()时,也需保证若两个引用的equals()相等,那么两个对象的的hashCode()一定相同,

 这两个方法都是来自java.lang.Object类,在Object中hashCode()返回的是对象的地址值映射的hash值,equals()方法是对两个对象的地址值进行的比较;如果equals()方法的返回值相同,说明两个对象的地址值也是相同的,所以hashCode()的返回值也是相同的。

---------------------------------------------------------------------------------

1)什么是hashCode()?

hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值,也就是哈希码,哈希码并不是完全唯一的,它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。 在Java中,哈希码代表对象的特征。

2 )Object 对象中 hashCode()方法:

是由c++实现,根据对象的地址算出来的int类型的数值,hashcode()方法提供了对象的hashCode值,是一个native方法,返回的默认值与System.identityHashCode(obj)一致。

Object 对象中 equals()方法:

判断两个引用是否指向堆中的同一块内存,即同一个对象

3)所有的类都继承Object,因此对equals()和hashCode()都可以重写,

对于hashCode(),java中许多api都有实现,不同的类对hashCode()方法有不同的实现,因此不同的类根据不同的规则去做自己的hash码,可以根据地址或者字符串或者数字算出来的int类型的数值

不同的对象有不同的哈希码算法例如: 
1、Object类的hashCode返回对象的内存地址经过处理后的结构,由于每个对象的内存地址都不一样,所以哈希码也不一样。 
2、String类的hashCode根据String类包含的字符串的内容,根据一种特殊算法返回哈希码,只要字符串所在的堆空间相同,返回的哈希码也相同。 
3、Integer类,返回的哈希码就是Integer对象里所包含的那个整数的数值,例如: 
Integer i1=new Integer(100); 
i1.hashCode的值就是100 。由此可见,2个一样大小的Integer对象,返回的哈希码也一样。 
由此可以看出Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的 字段等)映射成一个数值,这个数值称作为散列值。

4)hashCode()方法有啥用处呢?

Set集合:元素无序,但不重复。

那么这里就有一个比较严重的问题了:如何判断两个对象相等呢?这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。

 因为hashCode()可以返回该对象的特征,因此在HashSet集合(不允许有重复元素)中插入对象时,就可以利用待插入对象的hashCode值来判断是否可以插入(一般如果不重写hashCode()方法的话,hashcode的值就是对象的地址映射,因此就是地址值:hash值,进而判断该物理地址是否有元素了。。。)。。。。。。。。。。。。。。。。。。。

在向集合(如HashSet,TreeSet等)中添加元素的时候遵循的规则是:

   A 判断对象的hashCode的值是否相同,如果不相同,认为这两个元素不相同,如果相同,转入B。

   B判断两个对象的equals运算的值是否相同,如果不相同,认为两个对象是不相同的,

如果相同认为两个对象是相同的。

--------------------------------------------------------------------------------------------------------------

 所以,Java对于eqauls方法和hashCode方法是这样规定的: 
1、如果两个对象相同,那么它们的hashCode值一定要相同; 
2、如果两个对象的hashCode相同,它们并不一定相同 ; 

 如果一个类重写了equals()方法,则一定也要重写hashCode()方法,原因是:虽然equals()方法重写可以保证正确判断两个对象在逻辑是否相同,但是hashCode()方法映射的物理地址是不相同的,依然会将逻辑上相同的两个元素存入集合,但是第二个对象的内容会是Null.

2.这样的 a.hashcode() 有什么用,与 a.equals(b)有什么关系

两个对象的hashCode()值相等,两个对象不一定相等,

两个对象相等的规范是:两个对象的equals()相等,hashCode()也相等

 

3.有没有可能 2 个不相等的对象有相同的 hashcode

可能,hash冲突,使得不同的对象有相同的hash值

4.hashCode和equals的联系?

①两个obj,如果equals()相等,hashCode()一定相等

②两个obj,如果hashCode()相等,equals()不一定相等

原因:从散列的角度考虑,不同的对象计算哈希码的时候,可能引起冲突,大家一定还记得数据结构中冲突的解决方案吧

但是要这么设计,用两个函数,个人的理解是为了比较两个对象时更高效。

可以考虑在Java集合中,判断两个对象是否相等的规则是:

第一步,如果hashCode()相等,则查看第二步,如果两个hashCode()不相等,则两个对象不相等;

第二步,查看equals()是否相等,如果相等,则两obj相等,否则还是不相等。

为什么这样做?个人的理解是让适当的函数完成适当的功能,毕竟hashCode()比equals()在某种程度上来得快。

 5. 如何在父类中为子类自动完成所有的 hashcode 和 equals 实现?这么做有何优劣。

在覆盖equals方法的时候,你必须要遵守它的通用约定。下面是约定的内容,来自Object的规范[JavaSE6]

自反性。对于任何非null的引用值x,x.equals(x)必须返回true。

对称性。对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true

传递性。对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也必须返回true。

一致性。对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用该x.equals(y)就会一直地返回true,或者一致地返回false。

对于任何非null的引用值x,x.equals(null)必须返回false。

 

结合以上要求,得出了以下实现高质量equals方法的诀窍:

1.使用==符号检查“参数是否为这个对象的引用”。如果是,则返回true。这只不过是一种性能优化,如果比较操作有可能很昂贵,就值得这么做。

2.使用instanceof操作符检查“参数是否为正确的类型”。如果不是,则返回false。一般来说,所谓“正确的类型”是指equals方法所在的那个类。

3.把参数转换成正确的类型。因为转换之前进行过instanceof测试,所以确保会成功。

4.对于该类中的每个“关键”域,检查参数中的域是否与该对象中对应的域相匹配。如果这些测试全部成功,则返回true;否则返回false。

5.当编写完成了equals方法之后,检查“对称性”、“传递性”、“一致性”。

注意:

覆盖equals时总要覆盖hashCode 《Effective Java》作者说的

不要企图让equals方法过于只能。

不要将equals声明中的Object对象替换为其他的类型(因为这样我们并没有覆盖Object中的equals方法哦)

 

 

覆盖equals时总要覆盖hashCode

一个很常见的错误根源在于没有覆盖hashCode方法。在每个覆盖了equals方法的类中,也必须覆盖hashCode方法。如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常运作,这样的集合包括HashMap、HashSet和Hashtable。

在应用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法都必须始终如一地返回同一个整数。在同一个应用程序的多次执行过程中,每次执行所返回的整数可以不一致。

如果两个对象根据equals()方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。

如果两个对象根据equals()方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode方法,则不一定要产生相同的整数结果。但是程序员应该知道,给不相等的对象产生截然不同的整数结果,有可能提高散列表的性能。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值