面试基础知识加强
一、Java基础
BigDecial使用
- 比较用compareTo而不是equals因为它会忽略精度
- 使用入参为String的构造方法
- 除的时候需要指定精度,否则除不尽的时候会抛异常
- 四舍五入:RUND_HALF_UP
多态
含义:父类引用指向子类对象
特点:
- 前提是有继承或实现
- 只有在运行过程中才能知道具体调用的是哪个类的哪个方法
- 如果子类重新了父类的方法则运行的时候调用的是子类的方法,否则调用父类方法
作用
提高程序的的拓展性
接口和抽象类区别
共同点
- 都不能实例化
- 都可以包含抽象方法
- 都可以有默认实现方法(JAVA8之后接口可以有default默认实现)
不同点
- 接口定义的是一种规范,抽象类在我实际项目中我觉得主要的作用就是代码的复用,把一些公共处理逻辑放到抽象类中
- 类只能单继承,接口能多实现
关于hashCode和equals
hashCode()的作用
产生hash码,也称为散列码,这个哈希码的可以确定对象在哈希表中(数组)的索引位置。
对象进行eqals比较的时候,它会判断对象的hashCode值是否相等,hashCode不相等对象肯定不相等,只有hashCode相等的时候才会再去比较equals的,这个时候也相等表明是相同对象,因为hash存储的是key-vlue形式的键值对,所以查找速度很快。
为什么重写equals必须重写hashCode
因为两个对象如果要相等hashCode值必须相等。举个例子hashSet添加元素的时候。
NIO、BIO、AIO区别
他们是java支持的三种网络编程模型。
AIO不太了解主要讲BIO和NIO。
先从客户端发起连接请求服务端的大致处理方式来讲
- BIO是同步阻塞IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,简单示意图如下。
- Java NIO:同步非阻塞IO,服务器实现模式为一个线程处理多个请求连接,客户端发的连接请求都会注册到多路复用器上,多路复用器轮训到连接有I/O请求就处理。
适用场景来说
BIO适用于连接数目较少且固定的架构。NIO适用于连接数据较多且连接较短的架构,比如如聊天系统,弹幕系统。AIO 适用连接数目多且长的架构。
ArrayList为什么线程不安全
集合相关
ArrayList为什么线程不安全
添加元素的时候size++写操作不是原子性的,分两步先读取,后++
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
HashMap中为何链表长度大于8才转为红黑树
参考:https://zhuanlan.zhihu.com/p/348756860
总结
为什么不一开始就用红黑树?是时间和空间的平衡,因为树节点大小是普通节点大小的两倍这个源码里也有提到过还有红黑树的构建也是比较消耗性能的涉及到树的旋转之类的。
8是反复试验的结果,源码注释有提到过,链表长度大于8概率小于千万分之一。通常都不会转换成红黑树,只所以设计红黑树目的是为了防止一些实现很差的hashCode函数
java8HashMap头插改尾插原因
一、先看什么是头插法
JDk7 通过 hashcode&(Length-1)后的一系列异或运算计算出数组的 index:
1).如果这个 index 位没有元素则直接占位;
2).只有一个元素时,开始比较 key 是否是同一个对象,如果是同一对象则覆盖,否则把当前 entry.next 指向原来 entry,让其退位让贤,称为头插;
3).问题来了,当这个位置有 n 个 entry 时,则要遍历出每个 entry,然后去比较当前 key 与遍历出来的是否是同一个 key,是则接覆盖并退出循环,否则进行下一次遍历,都没有同样的 key 会遍历完整个 entry 链。既然都要遍历完整个 entry,为什么不直接在尾部插入呢,用尾插法不行么?
其实很简单,头插法大多数情况是方便第一和第二种情况的