• HashMap 底层结构、put 流程、扩容机制

    1.7是数组加链表,链表采用头插法。

    1.8以及之后,底层是数组链表加红黑树,链表采用尾插法,扩容因子是0.75,初始长度是16,新添加元素时候,首先使用Object类的hashcode方法计算新添加元素的hash值,拿hash值取余当前数组长度,得到数组的下标索引,然后判断当前下标索引处是否有元素,如果没元素直接添加,如果有元素则使用object的equals方法判断两个元素的值是否相等,如果相等则不添加,如果不等则使用拉链法解决hash冲突,将元素继续往下挂,当链表长度大于8,数组长度大于等于64,将自动转为红黑树。如果树节点数量小于等于6,红黑树会退化为链表

  • ConcurrentHashMap 如何保证线程安全

    1.7之前采用分段锁

    1.7之后使用cas+syncharonized锁

  • ArrayList 扩容机制

    初始容量是0,第一次添加元素的时候,初始化容量为10,新添加元素时,首先判断当前元素+1是否大于当前数组长度,如果大于当前数组长度,则触发扩容,,扩容后的数组长度是当前数组长度的1.5被,新的数组用Array.copyof()把旧数组的元素全部复制进去,再把新元素存入新数组尾部

  • String 为什么不可变

    因为string底层使用private fanil修饰的,他是不可被修改的,也是不可变的,对他进行修改时,其实是创建了一个新的string字符串,然后然后将变量引用地址指向新的字符串达到修改的效果,不能被继承,避免子类破坏不可变的特性

  • equals 和 hashCode 的关系

  • 反射、注解、泛型擦除

  • Java 异常体系

常见场景题:

  • HashMap 为什么线程不安全?

    他没有添加任何同步锁,所以说在多线程并发读写,扩容,插入时会产生数据丢失,死循环,数据错乱等问题,所以线程不安全,解决方案的话,使用hashtable,他底层使用的是syncharonized关键字,但是粒度太大,性能差,或者使用concurrentHashMap,底层使用分段锁和cas+syncharonized优化,高并发首选

  • ConcurrentHashMap 和 HashMap 有什么区别?

    concurrentHashMap线程安全的,1.7底层使用分段锁。1.8使用cas+syncharonized关键字进行优化

    hashmap是线程不安全的,单线程的情况下使用效率比较高,多线程并发put,扩容,查询不安全

  • equals 必须重写 hashCode?

    重写 equals 必须重写 hashCode,为了遵守 Java 对象相等规范,防止对象存入 HashMap、HashSet 等哈希集合时出现存取异常。

  • 自定义注解 + AOP 在项目里怎么用?

    项目里用自定义注解配合aop处理横切逻辑,例如操作日志,权限校验,防重复提交,先定义运行时注解做标识,Aop通过@annotation切点拦截带注解的方法,再通知中读取注解配置执行公共逻辑,业务方法添加注解完成增强,实现业务与通用代码解耦