Java集合相关 HashMap底层原理及面试问题总结

1.list和set的区别

都是继承collection父类,常用的存放数据的集合

list允许重复的元素,set不允许有重复元素

list为有序集合,按照插入时的顺序,set则是无序排列

2.ArraysList和LinkedList的区别

ArraysList:

允许对元素进行快速访问,从中间位置对集合进行插入或删除时,要对数组进行复制,移动,代价很高,所以它适合查找和遍历,并不适合insert和delete(数组实现)

LinkedList:

很适合数据的insert和delete,随机访问数据的速度较慢,还定义了List接口中没定义的方法,专门用于操作表头和表尾的元素,可以当堆栈、队列和双向队列使用(链表实现)

(数组和链表的区别)

3.HashMap和TreeMap的区别

HashMap:

数组形式储存Key Value,线程不安全,k/v允许null值,key不允许元素重复,value允许元素重复。不保证顺序为插入时的顺序,无序排序。hash的key值是先通过hashcode()方法计算出哈希值,接着通过计算得出下标。必须重写应用于key的equals和hashcode方法。

TreeMap:

基于红黑二叉树的NavigableMap实现,线程不安全,k/v不允许null值,key不允许元素重复,value允许元素重复。有序排序,顺序为插入时顺序。迭代输出结果为插入时顺序。

4.HashMap底层原理:

4.1HashMap的put(k,v)方法

1)先将k/v封装进Node对象中

2)通过hash()方法得出key的hash码

3)这时得出map的下标值,通过equals方法拿下标找是否有链表,拿key和链表上的每个节点的k进行比较,如果返回false,那么将value加在链表的最末端,如果返回true,将k对应的节点上的value进行替换。

4.2HashMap的get(k,v)方法

1)先调用k的HashCode()方法得出哈希值,并通过哈希算法转换成数组的下标

2)在数组中通过下标定位到某个位置上。这个位置上什么也没有,就返回null。如果有单向链表,就拿着key和单向链表上每个节点k去进行equals方法,如果所有equals方法都返回false,则get方法返回null。如果其中一个节点的k和参数k进行wquals返回true,那么此时该节点的value就是我们要找的value,get方法返回这个value

5.总结

为什么无序:

因为不一定挂在哪个单向链表中,所以加入顺序和取出的不一致

怎么保证不可重复:

使用equals方法来保证key不可重复,如key重复,balue就会覆盖。存放在HashMap集合key部分的元素,其实就是存放在HashSet集合中,则HashSet集合也是要重写hashCode()和equals()

扩容:

HashMap集合的默认初始化容量为16,默认加载因子为0.75,也就是当HashMap集合底层数组的容量达到75%,数组就进行扩容。HashMap集合初始化容量为2的倍数,为了达到散列均匀,提高HashMap集合的存取效率

哈希碰撞:

将多个key通过HashCode()得出的哈希值,输入得到相同的value就是哈希碰撞

扩容的加载因子为什么0.75:

时间成本和空间成本的折中。

时间成本:

如果负载因子是1时,虽然空间利用率提高了,但是带来的哈希碰撞的概率

HashMap中哈希碰撞解决方法用的拉链法,会导致链表越来越长,即使后面会转变为红黑二叉

树,但是因为查询效率很低,所以会导致时间成本上升

空间成本:

如果负载因子太低,会导致空间占用率太低,比如大小为64,32都未被使用。

所以为了双向平衡将负载因子设置为0.75

链表转红黑树的阈值为什么是8:

负载因子为0.75时,可以计算出哈希碰撞的概率

碰撞8次概率非常小基本不可能

所以将阈值设置为8,避免链表转红黑树这样耗性能行为发生

JDK1.8之后改动:

当单向链表的元素超过8个,将链表转为红黑树结构。如果红黑树元素低于6,红黑树转为单向链表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值