==和equals的区别?
- ==对比的是栈中的值,基本类型的值是变量值,引用对象的值时内存对象的地址
- Object对象的equals方法默认是==,故一般会重写,比如String的equals方法比较对象的值
ArrayList和LinkedList区别?
- 数据结构不同: ArrayList的底层数据结构是数组,LinkedList的底层数据结构是链表
- 应用场景不同: ArrayList的随机访问的时间复杂度是O(1), 故适合查找;LinkedList的删除/增加的时间复杂度是O(1), 故适合增加/删除
- LinkedList比ArrayList都实现List接口,并比ArrayList多实现了Deque接口, 故LinkedList也适合当队列
CopyOnWriteArrayList的底层原理是怎样的?
- CopryOnWrite通过数组实现的,添加元素时,会复制新的数组,写操作时在新数组上执行,读操作在旧数组执行
- 并且写操作时,防止出现并发写入丢失数据的问题
- 写操作结束之后原数组指向新数组
- CopyOnWriteArrayList允许写操作时读操作,大大提高了读取性能,因此适用于读多写少的场景,但是CopyOnWriteArrayList会比较占内存,同时读到的数据不是实时最新的数据,所以不适合实时性要求很高的场景。比如网站搜索关键字黑名单、白名单
ConcurrentHashMap的扩容机制
JDK1.7版本
- ConcurrentHashMap是基于Segument分段实现的
- 每个Sequment相当于一个小型的HashMap
- 每个Sequment内部会进行扩容,和HashMap扩容机制类似
- 先生成新数组,然后将旧元素转移到新数组中
- 扩容的判断也是每个Sequment内部判断的,判断是否超过阀值
JDK1.8版本
- 不易于Segument分段实现的
- 当某个线程进行put时,如果发现ConcurrentHashMap在扩容线程也一并扩容
- 如果某个线程put时, 发现没有正在进行扩容时,则将Key-value添加到ConcurrentHashMap中,然后判断是否超过阈值,超过了则进行扩容
- ConcurrentHashMap是支持多个线程同时扩容的
- 扩容之前也先生成一个新数组
- 在转移元素之前, 先讲原数组分组,将每组分给不同的线程进行元素的转移工作
HashMap扩容机制的原理
JDK1.7
- 数据结构: 数组+链表
- 先判断是否扩容,若扩容,则扩容为数组的两倍
- 然后将数组的元素以及链表转移到新数组上去
JDK1.8
- 数据结构: 数组+链表+红黑树
- 先判断是否扩容,若扩容,新数组长度为旧数组的长度的两倍
- 然后将旧元素的值转移到新数组上,只是相对于JDK1.7的版本,红黑树的转移会通过哈希算法得出的下标可能计算新数组上不同位置,从而可能出现几种情况:红黑树拆分为两个链表或者红黑树、链表+红黑树
List和Set区别
- List:有序, 可重复,按对象进入的顺序保存对象,可重复,允许多个Null对象,可以用iterator去除所有元素,再逐一遍历,还可以使用get(int index)获取指定下标元素
- Set:无序, 不可重复,最多允许一个null对象,取元素时只能用iterator取得所有元素,再逐一遍历元素
Java的异常体系
- Java所有异常来自于顶级父类Throwable
- Throwable下两个子类Exception和Error。
- Error是程序无法处理的错误,一旦出现这个错误,则程序被迫停止运行
- Exception分为CheckException和RuntimeException异常。RunTimeException常常发生在程序运行时,会导致当前程序线程运行失败。CheckException常常发生在程序编译过程中,会导致程序编译不通过
(阿里一面)HashMap的put方法?
面向对象
相较于面向过程,处理问题的角度不同,面向对象更注重对象、以及各自要做什么,而面向过程每一个步骤以及顺序。
比如洗衣机洗衣服
面向过程:
- 会拆解成一系列步骤: 1. 打开洗衣机 2.放衣服 3.放洗衣粉
4.清洗 5.烘干
面向对象:
- 人:打开洗衣机、放衣服、放洗衣粉
- 洗衣机:清洗、烘干
总结
从上面例子,面向过程比较直接高效,而面向对象更易于维护、复用和扩展
Super和extends的区别?
- <? extends T>表示包括T以内任何类的子类
- <? super T>表示包括T以内任何类的父类
InnoDB是如何实现持久化的?
- InnoDB通过Buffer Pool, Log Buffer,Redo Log,Undo Log来实现事务,以一个update语句为例:
- InnoDB在收到一个update语句后,会先根据条件找到数据所在页,并将在页缓存在Buffer Pool上
- 执行update语句,修改Buffer Pool中的数据,也就是内存中的数据
- 执行update语句生成一个RedoLog对象,并存入LogBuffer中
- 针对update语句生成unlog日志,用于事务回滚。
- 如果事务提交,那么ReLog对象进行持久化,后续还有其他机制将Buffer Pool中修改的数据页持久化到磁盘中
- 如果事务回滚,则利用undoLog日志进行回滚