经典面试题1(Java 的集合类,HashMap 的实现原理)

1.为什么重写 equals 还要重写 hashcode?

        1,理解为什么要重写?

        equals是比较两个对象是否相等,他和hashcode都是Object中的方法,我们先做一个假设,不去重写equals和hashcode方法,看下面这行代码:

Person a=new Proson("张三",18);

Person b=new Proson("张三",18);

        如果我们不重写equals方法,那么就会调用Object类中的默认方法,比较a和b的内存地址,但是由于没有重写方法,就会将相同内容的不同引用存放在不同的hashcode之中。不去重写hashcode,hashcode是本地方法,Java的内存是安全的,无法根据散列码来查看到两个对象的地址,但是hashcode就是由对象的内存地址运用哈希算法生成的。

        那么我们去重写equals,不重写hashcode方法,那么hashcode就是Object的默认方法,显而易见的是a!=b,从而推理就是a和b的hashcode值不相等。

        但是重写了equals方法,a.equals(b)的结果一定为true,这个结果就和上面相反,因为hashcode的原则,如果equals相等,那么hashcode也一定相等,所以hashcode一定要重写。

        有四条规律,或者是说原则:

  1. 两个对象相等,hashcode一定相等
  2. 两个对象不等,hashcode不一定不等
  3. hashcode相等,两个对象不一定相等
  4. hashcode不等,两个对象一定不等

        其次,对于重写hashcode方法来说也是一个提高效率的方法,首先先比较hashcode是否相等,如果不等也就不用比较equals的值。

        重写equals的方法是针对于在HashSet集合中的自定义的类对象,由于set集合是无序的,所以避免重复,我们才要重写。

2.== 和 equals 比较的区别

        “==”是比较基本数据类型;如果是引用数据类型,则比较所指向对象的地址值

        equals比较的是所指向的对象的地址值,一般情况下,重写之后比较的是对象的值。

        其中,如果equals没有重写,那么就是相当于“==”,这样比较的是引用类型所指的对象的地址值。

        String类中的equals是被重写的,会直接比较对象的值。

3.为啥有时会出现 4.0 - 3.6 = 0.40000001 这种现象?

        因为浮点数进行加减的时候是将其转换成二进制的形式来计算的,但是二进制的精度无法表示1/10,就像十进制无法表示1/3。

4.介绍 Java 的集合类

        主要分为:set list map

        Java容器分为Collection 和 Map 两大类,其中Collection集合的子接口有Set、List、Queue三种子接口,Map也是一个接口,但是不是Collection的子接口。

        List:一个有序容器,元素可以重复,可以插入多个null元素,元素都有索引。常用的实现类有 ArrayList、LinkedList 和 Vector。

        Set:一个无序容器,不可以存储重复元素,只允许存入一个null元素,必须保证元素唯一性。Set 接口常用实现类是 HashSet、LinkedHashSet 以及 TreeSet。

        Map:是一个键值对集合,存储键、值和之间的映射。 Key无序,唯一;value 不要求有序,允许重复。从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。Map 的常用实现类:HashMap、TreeMap、HashTable、LinkedHashMap、ConcurrentHashMap。

4.1说一下 HashMap 的实现原理?

        HashMap是基于Map接口实现的,允许由null键和null值的存在,存储的数据都是无序的。

        HashMap的数据结构是一个数组和链表的结合体,“链表散列”结构。

        它的核心是基于Hash算法是实现的:

  1. 存储时,如果出现相同hashcode的key时,有两种处理方法,如果key相同,就覆盖,如果key不同,就将key-value存入HashMap之中。
  2. 当我们想要put元素的时候,首先得到的是key的hashcode值,然后根据,Hash的算法计算出数组的下标。
  3. 获取时,找到对应的数组下标,然后判断key的值是否相同,然后直接返回,就是value。

4.2解决Hash冲突

        HashMap解决hash冲突的原理是,使用了数组的存储机制,将冲突的key放入到链表中,冲突就在链表中进行对比。

        数组和链表是Java中保存数据比较简单的数据结构,其中数组和链表各有各的优点和缺点,数组方便查找,但是删除和插入困难,耗时较多,链表却恰恰相反,查找需要从头开始,比较麻烦,但是删除和插入却十分方便。于是我们结合两者之间的优点,使用一种叫做拉链法的方式可以解决哈希冲突。(JDk1.7)

        拉链法就是将数组和链表组合起来,其中每一个数组就是一个链表,如果遇到hash冲突,就可以将hash冲突的值放入链表之中。

        在JDK1.8之后,虽然也还是将数组和链表组合在一起,但是当链表的长度大于一个阈值(8)的时候,就会将链表转换为红黑树,用来减少搜索的时间,由于红黑树是一个自平衡的二叉树,所以时间复杂度为O(logn)

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会Java的MING

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值