面试邀请来得有突然,记录一下有些问题以及答案。
ArrayList 是线程安全的吗,怎样保证他线程安全。
原因:
其实大部分集合类都不是线程安全的,其关键的原因在于添加元素的底层实现,因为在arrayList的add()中:
elementData[size++] = e;
这一步包括了自增和赋值,因为当线程A执行了赋值以后,暂停转而运行其他的线程,但是还没扩容,就会导致,B线程的值直接覆盖A的值,
解决:
调用Collections.synchronizedList方法 ,其原理也就是将ArrayList里的方法添加synchronized关键字,也就是加锁,也就是经典的装饰器模式。
HashMap会出现什么问题,如何解决?
首先HashMap是一个高效的数据结构,可以在O(1)时间复杂度查询数据,原理大致为:将Key通过Hash算法得到一个地址值,再获取内存中想要的数据,但是Hash算法存在缺陷,就是不同的Key值通过计算得到的地址值又很小的几率相同,这就是Hash冲突。
解决方法:
-
开放寻址法:
它的核心思想就是重新探测新的位置来解决冲突,如何寻找新的地址:
1.线性探测法:
当向Hash表中插入数据时,发现该地址已经有数据了,那就从这个位置开始在数组中往后查找,直到找到空闲位置为止;缺点是随着不断填充,空闲的位置变少,探测的时间就会增加,
2.二次探测法:
探测的下标为hash(key)+0² 、 hash(key)+1² …
3.双重哈希法:
使用多个hash函数计算key ,如果第一个hash函数计算出来的地址被占用了,就调用第二个函数 ,直到找到空闲位置为止; -
链表法:
该方法更常用,原理为:在hash表中每一个桶或者槽(slot) 都会对应一个链表,将hash值相同的元素放到相同槽位的对应链表中,插入数据的时候,只需要通过hash函数计算出对应的hash值,然后添加到链表之后。链表法性能取决于hash函数的性能,尽量保证链表长度足够小。