1:概念:通过某种函数使元素的存储位置与它的关键码能够建立一一映射的关系,提高了搜索效率,时间复杂度为o(1).
2:哈希函数:key%数组的长度
3:foreach的循环对象一般是一个集合,List、ArrayList、LinkedList、Vector、数组等(遍历时常用)
4:在存放数据的时候难免会发生冲突,比如4和44,他俩经过散列函数的计算都是4,这样就产生了冲突。避免冲突的方法就是负载因子调节,负载因子是填入表中的元素/散列表的长度 ,java限制了负载因子为0.75.
5:如果发生冲突的无法被避免的时候,就要解决冲突,第一种解决冲突的方法闭散列,如果在存放数据的时候,哈希表没有被装满,还有空的位置,那么可以将key装到冲突位置的下一个空的位置中,那么怎么寻找下一个空位置呢,第一种方法叫做线性探测 依次往后探测,直到找到下一个空位置即可,但是这中方法会把冲突的元素都放在一起,不是很好。另一种方法为了避免这个问题就采用了二次探测,但是这两中方法的缺陷就是空间利用率低。
6:另一个解决冲突的方法是开散列,也叫链地址法,也叫哈希桶, 链地址法其实就是每一个数组放的都是链表的地址,链表长度一般为8.超过8的话就转化为红黑树了。
9:在进行插入的时候一旦超过规定的长度,就要进行扩容,扩容不仅仅是简单的复制,要对原来哈希桶的值进行重新哈希,比如原来长度为10 ,4和14,44的key值都相同,但是如果扩容成20,4、14、44的key值就不同了。
public void resize(){
Node[] newarray=new Node[2*this.array.length];
for (int i = 0; i <this.array.length ; i++) {
Node cur=array[i];
Node curnext=null;
while(cur!=null){
//记录cur的下一个节点
curnext=cur.next;
int index=cur.key%newarray.length;
cur.next=newarray[i];
newarray[i]=cur;
cur=cur.next;
}
}
this.array=newarray;
}
10:hashcode和equals的区别?
//如果在hashmap当中来说的话,作用分别如下:
//1、hashcode是定为当前元素,需要在当前数组当中的下标
//2\ equals是需要在hashcode定位的某个下标中,遍历链表。比较哪个key是相同的。
//hashcode相同 equal不一定相同。
//如果以后hashmap当中,需要存放自己自定义的数据类型
//那么这个数据类型一定要同时重写hashcode和equals方法。
11:面试问题
//如果new HashMap(19),bucket数组多大? 一般空间大小都是2的次幂,所以大小应该是2的5次方 32.
//HashMap是什么时候开辟bucket数组占用内存? new完 还没有分配内存 数组大小为0。第一次put的时候才分配
//hashMap什么时候扩容? 根据负载因子 0.75,
//当两个对象的hashcode相同会发生什么? 哈希碰撞 产生冲突 尾插法
//如果两个键的hashcode相同,你如何获取值对象?在当前hashcode的数组位置开始遍历链表
//你了解重新调整hashmap大小存在什么问题吗? 需要重新哈希