前言

因为要最近要面试,冲刺挑战一下,下面是准备的中级面试题,具体如下:

  1. 设计模式篇
  2. Hashmap篇
    ...

一、设计模式篇

1.常用的设计模式
答:单例:保证Jvm中只有一个实例,一般用在配置、Spring bean,servlet
   工厂:创建对象和使用过程完全分开
   代理:在目标方法前和目标方法后实现增强
   策略、模板、责任链、观察者、装饰、门面模式	

2. 策略模式
答:存在共同行为,但不同策略,交给子类来实现,一般用在解决多重if判断、设计排序算法、支付接口

3.模板模式
答:提供共同骨架,相同放在父类,不同交给子类(继承)

4.责任链模式
答:客户端发送请求,会将对象顺序执行一遍。场景:过滤器,工作流、ERP系统、风控系统

5.装饰模式
答:不影响当前代码实现增强。场景:多级缓存、IO流,mybatis一级和二级

6.代理模式
答:目标前后实现。场景:AOP、mybatis对象Mapper、事物、日志、RPC调用

7.观察者模式
答:实现带代码的监听(生产者、消费者)。场景:MQ,zookeeper、redis、配置中心

8.适配器模式
答:将不能被调用的接口采用适配器就可以调用,场景:用在多环境不同版本兼容,mybatis日志

9.装饰和代理区别
答:装饰不影响当前代理实现增强,代理是在目标逻辑前后实现

10.动态代理和静态代理区别
答:静态代理需要编写动态用反射字节码生成代理类(重写)

11.spring中如何使用JDK和cglib代理
答:被代理的类有实现用jdk,没有实现用cglib

12.单例模式创建方式
答:懒汉式、饿汉式、Holder、枚举、内部类、静态

13.懒汉式和饿汉式区别
答:懒汉先天性不安全,需要时实例化加载,需要人为加锁,饿汉式线程安全,启动时候加载,所以启动慢

14.静态内部类和双重检验锁区别
答:静态内部类用关键字static,双重锁采用lock锁

15.如何破解单例
答:反射,序列化

16.序列化和反序列化
答:将一个对象对象序列化到硬盘,反之反序列化

17.序列化协议
答:Json、hessian、protobuf

18.那些单例最安全
答:枚举(不能被破解)

二、Hashmap篇

1、hashcode与equals区别
答:如果对象的hashcode相等,内容不一定相等
equals内容相等,,hashcode一定相等

2、重写equals为啥要重写hashcode
答:因为要equals内容相等,hashcode不一定要冲突

3、hashmap和hashtable区别
答:hashmap可以存放空,不安全,效率高,hashtable加锁,安全,不能放空

4、如何理解hashcode碰撞
答:对象不等,但hashcode会相同,导致hashcode碰撞

5、如何理解hashcode碰撞

6、hashmap的put方法如何实现
答:1.Jdk1.7采用数组+链表通过头插入法(在多线程扩容数组,可能会产生死锁)实现,采用hashEntry封装键值对。
2.根据key计算hashcode得出index存放下标,如产生碰撞则采用链表存放。
3.hashmap根据key查询键值对时间没有产生冲突情况下时间复杂度为O1,查询hashmap产生冲突的key时间复杂度为ON,所以1.8中当链表长度大于8并且长度为64情况下转红黑树存放

7、hashmap扩容如何实现
答:hashmap数组默认大小16,加载因子0.75,扩容对原数据乘2

8、扩容加载因子为啥是0.75
答:科学家证明0.75是黄金比例,加载因子小,key冲突比较小,浪费空间,因子越大,冲突较多,节约内存

9、hashmap为空,数组存放在那个位置
答:存放下标为0,第一个链表

10、haskmap是否可以存放自定义对象为key
答:可以,因为是泛型

11、hashmap在Jdk1.7和jdk1.8中区别
答:1.7:数组+链表,1.8:数组+链表+红黑树

12、jdk1.7中扩容死循环有遇见吗
答:在1.7中使用头插入法,多线程情况下会导致死循环

13、hashmap在Jdk1.8较1.7有哪些改进
答:尾插入法、解决红黑树、链表长度 > 8就转换红黑树

14、hashmap在1.8中为啥改成红黑树
答:如果下标index冲突过多,导致链表长度过长,时间复杂度为On,查询速度慢,当链表长度 > 8并且容量 > 64,转成红黑树,时间复杂度变O(long)

15、hashmap不安全,有哪些替代方案
答:ConcurrentHashmap、conllections、synize加锁