Java面试必问——HashMap面试题(附答案)
2023-03-27 16:01:13
Hashmap是java程序员同时,由于使用频率最高的映射处理数据类型,Hashmap有很多好处,Hashmap将用作电子商务应用的缓存。这已经成为java面试的必考内容,所以今天整理了这篇文章10道Hashmap面试题,都是在各大互联网公司正在准备面试的朋友一定不能错过以下内容。
1、Hashmap的底层原理是什么?
答:hashmap内部是一个数组+链表的数据结构。在put元素中,元素的key将首先进行hash操作,然后通过hash值和数组长度进行位置操作,获得真正的元素下标。此时,判断下标是否有元素。如果有元素,将元素插入链表。得到它时,用同样的方法得到元素的下标。如果这个数组只下标一个元素,那么这个元素就是map的value,如果是链表结构,循环链表就会得到map的value。
2、hashmap是否安全?
答:非线程安全,因为如果在高并发下,会导致在某一点上index下有一个循环链表,如果你得到一个不存在的key,key计算的index值正好等于前一个循环链表所在的index值,就会出现死循环。在这里,您还可以通过解释代码详细介绍如何生成循环链表。
3、如何保证LinkedHashmap和Treemap有序?
答:LinkedHashmap继承从Hashmap内部维护链表,以保持其内部元素的插入顺序,并按插入顺序迭代;Tremap按key的自然顺序排序,如果需要,可以继承Comparator接口。
4、默认情况下,hashMap的初始长度是多少?为什么这么规定?
答:默认初始长度为16.为了服务于key映射到index的hash算法,该算法使用hash(key)&length-1.位置操作可以保证性能,效果与模具相同。16-1是为了确保第二进制位数为1,因此只要hash函数计算结果均匀,index也均匀。
5、如何构建线程安全的Map?
答:可以用hashtable和currentHashMap,Hashtable是实现synchronize关键词的hashmap,效率很低,一般不推荐使用。put时,key获得hash值,从hash值定位到segment,获得可重新锁定,然后通过hash值获得特定的index,插入或覆盖物体,释放锁。
获得时,key获得hash值,从这个hash值定位到所在的segment,再定位到具体的index。java8改为synchronize和CAS,底层改为链表+红黑树结构,存储数据由hashentry改为node,valatile关键字修改value和next,以确保其多线程下的可见性。
计算put时key的hash值,判断是否需要初始化。如果定位的node太空,则使用CAS插入数据。如果hashcode==MOVIED==-一是扩容,否则用synchronize锁写入数据。得到的时候还是通过hashcode寻址,如果是链表,则按链表方式寻址,如果是红黑树则按红黑树方式寻址。
6、Hashmap的工作原理和Hashmap的get()方法的工作原理?
答:Hashmap是基于hashing的原理,我们使用putt(key, value)将存储对象存储到Hashmap中,使用get(key)从HashMap中获取对象。当我们将键和值传递给put()方法时,我们首先对键调用hashcode()方法,返回hashcode以找到bucket位置存储entry对象。Hashmap作为Map存储在bucket中的键对象和值对象.Entry。
7、当两个对象的hashcode相同时会发生什么?
答:hashcode是一样的,所以两个对象是相等的,hashmap会抛出异常,或者不会存储。有两种方法:equals()和hashcode()。即使hashcode相同,两个对象也可能不相等,因为hashcode相同,所以它们的bucket位置相同,‘碰撞’会发生。由于Hashmap使用链表存储对象,这个Entry(包含键值对的Map.Entry对象)将存储在链表中。
8、可以用CocurrentHashmap代替Hashtable吗?
答:因为越来越多的人使用ConcurrentHashmap。我们知道Hashtable是synchronized,但是concurenthashmap的同步性能更好,因为它只根据同步级锁定map的一部分。当然,ConcurentHashmap可以代替Hashtable,但Hashtable可以提供更强的线程安全性。
9、为什么String?、像Interger这样的wraper类适合作为键?”
答:String、像Interger这样的wraper类作为Hashmap的键再合适不过了,而且String最常用。因为String是不可改变的,也是final,equals()和hashcode()方法已经重写。其他wrapper类也有这个特点。不可变性是必要的,因为为为了计算hashcode(),有必要防止键值变化。如果键值在放入和获取时返回不同的hashcode,则无法从hashmap中找到您想要的对象。线程安全等不可变性等优点。如果你只能通过将field声明为final来保证hashcode不变,请这样做。因为equals()和hashCode()是在获取对象时使用的,所以正确重写键对象是非常重要的。如果两个不相等的对象返回不同的hashcode,碰撞的概率会更小,从而提高hashmap的性能。
10、如果Hashmap的大小超过了负载因子(load factor)如何定义容量?
答:默认负载因子的大小为0.75,也就是说,当一个map填满75%的bucket时,就像其他集合类(如arraylist等)一样,它将创建一个bucket数组,将原始hashmap大小的两倍,以重新调整map的大小,并将原始对象放入新的bucket数组中。这个过程叫rehashing,因为它调用hash找到新的bucket位置。
以上内容就是小编