1. HashMap的扩容机制
- JDK 1.7
扩容是针对数组进行扩容,链表是不需要进行扩容的。扩容时先生成原来数组两倍大小的新数组,在把原来老数组上的链表上的元素转移过去。具体在转移链表中元素的步骤是:取每个元素的 key,基于新数组长度,计算出每个元素在新数组中的下标,将元素添加到新数组上去。最后,当所有的元素都转移完成后,将新数组赋给 HashMap 的 Table 属性
- JDK 1.8 版本
先生成新数组,遍历老数组中每个位置的链表或者红黑树,如果是链表的话,就直接将链表中的每个位置重新计算下标,然后添加到新数组上去。如果是红黑树的话,遍历红黑树,计算出红黑树中每个元素对应在新数组中的下标位置。算法为:
先统计每个下标位置的元素个数,如果该位置的元素个数超过了8, 则生成一个新的红黑树,并将根节点添加到新数组的对应位置。如果没超过8,则生成一个链表,将链表的头节点添加到数组的对应位置。
最后,当所有的元素都转移完成后,将新数组赋给 HashMap 的 Table 属性。
2. CopyOnWriteArrayList 的底层原理
出现原因:首先,CopyOnWriteArrayList 要解决的是 ArrayList 线程不安全的问题,所以我们需要一个线程安全的 ArrayList 。
add操作原理: CopyOnWriteArrayList 实现了对写线程的加锁,这里要注意:CopyOnWriteArrayList 并未实现读写线程的串行,其add方法在内部实现时,新建一个新数组,为新数组添加新的元素,添加结束后,再将新数组赋给 List。通过这种方式实现 写线程运行时,不影响读线程运行,从而提高了效率。
使用场景:CopyOnWriteArrayList 适用于读多写少的场景,但是其不适用实时性要求高的场景。除此之外,CopyOnWriteArrayList 的内存消耗高,因为其在 add 操作时,需要新建一新数组。
3. 字节码是什么,有什么好处
Java 源文件(即 *.java)经过 javac 编译器被编译为 java字节码文件(即 *.class )。如下图所示:
优点: Java 字节码文件可以在各种操作系统上运行,但是要求操作系统上要有 java 的运行环境 jdk 或者 jre。因为Java 字节码的存在,使得 Java 语言可以实现 跨平台。除此之外,其也提升了代码执行的性能,因为编译器可做一些优化,比如锁消除、标量替换、方法内联等。
4. Java 的异常体系
Java 中的异常体系如下:
异常处理具有一顶级父类 Throwable, Throwable 具有两个子类 Exception 和 Error 。
Error 是指非常严重的错误,如栈溢出、内存溢出等异常,其可能是操作系统层面产生的问题。对 Error 类异常我们一般不去捕获,等待它自己抛出即可。
而 相比之下 Exception 类的异常就没有那么严重了,我们可以自己写程序来解决。其又分为 运行时异常 和 非运行时异常。运行时异常是指程序编译可以通过,但是运行时会抛出的异常,比如空指针异常、数组下标越界异常等。而非运行时异常,是程序编译都通过不了的异常,比如 IO异常 或 SQL 异常。