面试2

## 数据结构

 

1. HashMap的原理,内部数据结构?

    - 底层使用哈希表(数组 + 链表),当链表过长会将链表转成 红黑树以实现O(logn) 时间复杂度内查找

1. 讲一下 HashMap 中 put 方法过程?

    1. 对 Key 求 Hash 值,然后再计算 下标。

    1. 如果没有碰撞,直接放入桶中,

    1. 如果碰撞了,以链表的方式链接到后面,

    1. 如果链表长度超过阀值(TREEIFY_THRESHOLD == 8),就把链表转成红黑树。

    1. 如果节点已经存在就替换旧值

    1. 如果桶满了(容量 * 加载因子),就需要 resize。

1. HashMap 中 hash 函数怎么是是实现的? 还有哪些hash 的实现方式?

    1. 高 16bit 不变,低 16bit 和高 16bit 做了一个异或

    1. (n - 1) & hash --> 得到下标

    1. 还有哪些 Hash 实现方式:可以参考之前的博客 [Effective Java学习笔记-- hashCode()](../reading-notes/Effective-Java.md)

1. HashMap 怎样解决冲突,讲一下扩容过程,假如一个值在原数组中,现在移动了新数组,位置肯定改变了,那是什么定位到在这个值新数组中的位置,

    - 将新节点加到链表后,

    - 容量扩充为原来的两倍,然后对每个节点重新计算哈希值。

    - 这个值只可能在两个地方,一个是原下标的位置,另一种是在下标为 <原下标+原容量> 的位置。

1. 抛开 HashMap,hash 冲突有那些解决办法?

    - 开放定址,链地址法

1. 针对 HashMap 中某个 Entry 链太长,查找的时间复杂度可能达到 O(n),怎么优化?

    - 将链表转为红黑树, JDK1.8 已经实现了。

1. 数组和 ArrayList 的区别;

    1. 数组可以包含基本类型和对象类型,ArrayList 只能包含对象类型

    1. 数组大小固定,ArrayList 大小可以动态变化

    1. ArrayList 提供了更多的特性(`addAll`、`removeAll`)。

1. Arraylist 如何实现排序

    - `Collections.sort(List<T> list)`;

    - `sort(List<T> list, Comparator<?super T> c)`;

1. HashMap

    1. 数组 + 链表方式存储

    1. 默认容量: 16(2^n 为宜,若定义的初始容量不是 2^n,容量会定义为大于该初始容量的最小2^n)

        -例如:初始容量为13,则真正的容量是16.

    1. put:

        1. 索引计算 : ((key.hashCode() ^(key.hashCode() >>> 16)) & (table.length - 1))

        1. 在链表中查找,并记录链表长度,若链表长度达到了TREEIFY_THRESHOLD(8),则将该链转成红黑树。

        1. 若在链表中找到了,则替换旧值,若未找到则继续

        1. 当总元素个数超过容量*加载因子时,扩容为原来 2 倍并重新散列

            - (元素的下标要么不变,要么变为【原下标+原容量】)。

        1. 将新元素加到链表尾部

        1. 线程不安全

1. HashTable

    1. 数组 + 链表方式存储

    1. 默认容量: 11(质数 为宜)

    1. put:

        1. 索引计算 : (key.hashCode() &0x7FFFFFFF)%table.length

        1. 若在链表中找到了,则替换旧值,若未找到则继续

        1. 当总元素个数超过容量*加载因子时,扩容为原来 2 倍并重新散列。

        1. 将新元素加到链表头部

    1. 对修改 Hashtable 内部共享数据的方法添加了 synchronized,保证线程安全。

1. HashMap ,HashTable 区别

    1. 默认容量不同。

    2. 索引计算方式不同。

    3. HashMap 特有的将过长链表转换为红黑树。

    4. 新元素的位置不同。

    5. 线程安全性

1. HashMap、ConcurrentHashMap 区别。

    1. 索引计算消除了最高位的影响

    1. 默认容量: 16(若定义了初始容量(c),容量会定义为大于(c + (c >>>1) +1) 的最小2^n)

        - 例如:初始容量为 13,则真正的容量是 32.

    1. 线程安全,并发性能较好

        - 并发性能好的原因是 ConcurrentHashMap 并不是定义synchronized 方法,而是在链表头上同步,不同的链表之间是互不影响的。

1. ConcurrentHashMap 原理

    1. 最大特点是引入了 CAS(借助 Unsafe 来实现【native code】)

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值