一、Java 基础
1. Java 和 C 语言有什么区别?Java 好在哪里?
2. 怎么理解 Java 的跨平台性,一次编译到处运行?
3. 面向对象和面向过程的区别?
4. 如何理解面向对象三大特性:封装、继承、多态?
5. 类继承会有什么问题吗,一般什么情况下才会去用继承?
6. 为什么重写 equals 方法还要重写 hashcode 方法?
7. 深克隆和浅克隆
8. 反射相关
9. 注解的实现原理
10.Lambda 表达式的优缺点?
11.Stream 流式编程的好处?终止方法和延迟方法的区别是?终止方法存在
的意义是什么?
二、Java 集合
1. HashMap 底层实现(JDK1.7 使用数组+链表;JDK1.8 使用数组+链表+红
黑树)
2. HashMap 为什么要引进红黑树?为什么不用其他的平衡二叉树之类的?
红黑树的优势在哪里?(AVL 树的旋转比红黑树的旋转更加难以平衡和
调试,需要更高的旋转次数)
3. 链表会转化为红黑树的两个条件是?(①链表的长度达到 8;②HashMap
底层使用的 table 数组长度 length 达到 64;如果不满足后者,将会触
发扩容方法)
4. 链表长度大于 8 转化为红黑树,小于 6 红黑树转化为链表;为什么不直
接设置成大于 8 转化成红黑树,小于 8 转化成链表;(中间有个差值 7
进行过渡是为了避免链表和树频繁转换,如果一个 HashMap 不停的插
入、删除元素,链表个数在 8 左右徘徊,就会频繁的发生树转链表、链
表转树,效率会很低)
5. 把链表转化为红黑树的阈值是 8,为什么不设置成其他值?(遵循泊松
分布,链表长度超过 8 的概率非常小)
6. HashMap 扩容机制,即 resize 方法?(JDK 1.7 会重新计算每个元素的
哈希值,JDK1.8 是通过高位运算(e.hash & oldCap)来确定元素是否
需要移动,如果运算结果值为 0,那么元素扩容后位置不变,结果值为
1 表示元素在扩容时位置发生了变化,新的下标位置等于原下标位置 +
原数组长度)
7. HashMap 添加元素的步骤(put 方法)、计算集合元素个数(size 方
法)
8. HashMap 为什么是线程不安全的?(同时新增元素、同时扩容导致数据
丢失,jdk1.7 头部倒序插入出现死循环导致 CPU 占用 100%)
9. HashMap 默认的加载因子是 0.75,为什么不设置成 1 或者 0.5(从容量
和性能考虑)