这篇文章我花了两天编辑,是目前我能找到的几乎所有的问题。所以你们如果能全部掌握,基本就能收割 offer 了。时间有限的话,针对自己的情况优先选最有可能被问到的问题来准备。
文中的200道题大部分都包含了答案,希望对要参加面试的读者有一定的帮助,这是小编为了准备面试阿里二面所准备的面试题,出来收集了200道高级Java面试题之外,小编同时整理的Java核心笔记,Java架构面试专题整合200道(pdf文档)
注意:因为我并没有系统的学习多线程编程,所以并发相关的问题我只是大概了解一下,目前并不深入讨论(面试时直接说明即可)
- 数据结构
- 算法题
- Java基础
- Java高级
- 三大框架
- 数据库
- 操作系统
- 计算机网络
- 分布式,集群等高级主题
- 技术开放题
- 题目参考
- 解答参考
文章篇幅很长很长,我花了很多心思,希望大家看下去
数据结构
- 讲一下 HashMap 中 put 方法过程?
- 对 Key 求 Hash 值,然后再计算 下标。
- 如果没有碰撞,直接放入桶中,
- 如果碰撞了,以链表的方式链接到后面,
- 如果链表长度超过阀值(TREEIFY_THRESHOLD == 8),就把链表转成红黑树。
- 如果节点已经存在就替换旧值
- 如果桶满了(容量 * 加载因子),就需要 resize。
- HashMap 中 hash 函数怎么是是实现的? 还有哪些 hash 的实现方式?
- 高 16bit 不变,低 16bit 和高 16bit 做了一个异或
- (n - 1) & hash --> 得到下标
- 还有哪些 Hash 实现方式:可以参考之前的博客 Effective Java 学习笔记 -- hashCode()
- HashMap 怎样解决冲突,讲一下扩容过程,假如一个值在原数组中,现在移动了新数组,位置肯定改变了,那是什么定位到在这个值新数组中的位置,
- 将新节点加到链表后,
- 容量扩充为原来的两倍,然后对每个节点重新计算哈希值。
- 这个值只可能在两个地方,一个是原下标的位置,另一种是在下标为 <原下标+原容量> 的位置。
- 抛开 HashMap,hash 冲突有那些解决办法?
- 开放定址,链地址法
- 针对 HashMap 中某个 Entry 链太长,查找的时间复杂度可能达到 O(n),怎么优化?
- 将链表转为红黑树, JDK1.8 已经实现了。
- 数组和 ArrayList 的区别;
- 数组可以包含基本类型和对象类型,ArrayList 只能包含对象类型
- 数组大小固定,ArrayList 大小可以动态变化
- ArrayList 提供了更多的特性(addAll、removeAll)。
- Arraylist 如何实现排序
- Collections.sort(List<T> list);
- sort(List<T> list, Comparator<? super T> c);
- HashMap
- 数组 + 链表方式存储
- 默认容量: 16(2^n 为宜,若定义的初始容量不是 2^n,容量会定义为大于该初始容量的最小 2^n)
- 例如:初始容量为 13,则真正的容量是 16.
- put:
- 索引计算 : ((key.hashCode() ^ (key.hashCode() >>> 16)) & (table.length - 1))
- 在链表中查找,并记录链表长度,若链表长度达到了 TREEIFY_THRESHOLD(8),则将该链转成红黑树。
- 若在链表中找到了,则替换旧值,若未找到则继续
- 当总元素个数超过容量*加载因子时,扩容为原来 2 倍并重新散列
- (元素的下标要么不变,要么变为【原下标+原容量】)。
- 将新元素加到链表尾部
- 线程不安全
- HashTable
- 数组 + 链表方式存储
- 默认容量: 11(质数 为宜)
- put:
- 索引计算 : (key.hashCode() & 0x7FFFFFFF)% table.length
- 若在链表中找到了,则替换旧值,若未找到则继续
- 当总元素个数超过容量*加载因子时,扩容为原来 2 倍并重新散列。
- 将新元素加到链表头部
- 对修改 Hashtable 内部共享数据的方法添加了 synchronized,保证线程安全。
- HashMap ,HashTable 区别
- 默认容量不同。
- 索引计算方式不同。
- HashMap 特有的将过长链表转换为红黑树。
- 新元素的位置不同。
- 线程安全性
- HashMap、ConcurrentHashMap 区别。
- 索引计算消除了最高位的影响
- 默认容量: 16(若定义了初始容量(c),容量会定义为大于(c + (c >>> 1) +1) 的最小 2^n)
- 例如:初始容量为 13,则真正的容量是 32.
- 线程安全,并发性能较好
- 并发性能好的原因是 ConcurrentHashMap 并不是定义 synchronized 方法,而是在链表头上同步,不同的链表之间是互不影响的。
- ConcurrentHashMap 原理
- 最大特点是引入了 CAS(借助 Unsafe 来实现【native code】)
- CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。
- Unsafe 借助 CPU 指令 cmpxchg 来实现
- 使用实例:
- 对 sizeCtl 的控制都是用 CAS 来实现的
- sizeCtl :默认为0,用来控制 table 的初始化和扩容操作。