Java_面试札记
Java_面试札记
为了不死,我愿献出生命
背景:记录下寄几和friend在2020年Java面试中遇到的problem。
1、MySQL索引结构?
基本上所有的索引都是B-Tree结构,还有一部分是HASH索引;B-Tree数据结构的简单说明:
1、B-Tree结构首先是分成很多节点,一个节点上面有很多的关键字(建立索引的字段),这些关键字在节点上是按照顺序排列的;
2、在一个节点上,每一个关键字的前面都有一个下个节点的指针,所以在一个节点上面,关键字的数量总是比节点的数量少一个;
3、每个节点指针指向下一个节点。
2、MySQL索引分类?
1、普通索引index:加速查找;
2、唯一索引
主键索引:primary key:加速查找+约束(不为空且唯一);
唯一索引:unique:加速查找+约束(唯一);
3、联合索引
-primary key(id,name);联合主键索引
-unique(id,name);联合唯一索引
-index(id,name);联合普通索引
索引按照功能分类:
1、主键索引:一张表中最多有一个主键索引,且字段不能为NULL,不能重复;
2、唯一索引:一张表中可以有多个唯一索引,且字段可以为NULL,但不能有重复值;
3、普通索引:一张表中可以有多个普通索引,且值可以为NULL,并且值可以重复;
4、全文索引:全文索引就是将该字段的信息加以拆分和组合,形成一份清单,和sphinx全文索引一样;
5、复合索引:一个索引如果建立在多个字段上,那该索引就称为复合索引。
说明:其实这些索引的数据结构都是一样的B-Tree结构,只是他们对字段信息的约束条件不一样。
4、索引的使用有了解?
使用索引应该满足左原则,如:
1、like查询时,不能以通配符开始;
2、复合索引,如果想使用第二个关键字索引,那么第一个关键字索引必须要确定;
5、对A、B、C三个字段建立联合索引,然后使用ABC三个字段查询,哪个字段会击中索引?
根据查询字段的位置不同来决定,如查询A、A,B、A,B,C、A,C都可以走索引的,其它条件的查询不走索引;组合索引有“最左前缀”原则,就是只从最左面的开始组合,并不是所有只要含有这三列存在的字段的查询都会用到该组合索引。
6、ES处理数据?
ElasticSearch是一个开源的搜索引擎。
ES的简介及使用:https://www.cnblogs.com/wihainan/p/7064943.html
7、Java中对象作为参数传递,是传值还是传引用?
值传递就是把参数的值给你,调用函数时将实际参数复制一份传递到函数中,这样函数内部对参数内部进行修改不会影响到实际参数;
引用传递就不一样了,它直接把参数的实际地址给调用函数了,函数内部可直接修改该地址内容,会影响到实际参数;
在Java中,当对象最为参数传递时,实际上传递的是一份“引用的拷贝”,即值传递。
8、new一个对象是如何存储的?
堆内存是用来存放由new创建的对象和数组,即动态申请的内存都存放在堆内存中;
栈内存是用来存放在函数中定义的一些基本类型的变量和对象的引用变量;
如:new一个person,Person person = new Person();右边部分new Person()保存在堆中,左边对象的引用person保存在栈中。
9、解释性SQL?
explain select name from table;explain显示了MySQL如何使用索引来处理select语句以及连接表,可以帮助选择更好的索引和写出更优化的查询语句。
10、Linux命令查看文件大小?
ll -lht, ls -l
11、Linux命令查看内存大小?
free -m
12、Spring中的FactoryBean和BeanFactory的区别?
BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean;
在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的;(这些bean为普通bean)
但对FactoryBean而言,这个Bean不是简单的bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。(非普通bean)
13、分库分表按照什么规则?
清澜山的智慧校园系统是按照业务实现分库的,如人员数据库、车辆数据库、主数据数据库等;
分表可以水平分割、垂直分割;
水平分割:表中数据量大时,可以适当的进行水平分割,将部分数据移动到另一张表中;
垂直分割:表中字段过多时,可以适当的进行垂直分割,将部分字段移动到另一张表中。
14、SpringBoot的启动过程?
1、启动类中调用:SpringApplication.run(xxx.class,args)方法;
2、在SpringApplication的run方法中有两个步骤,首先创建SpringApplication对象,然后再调用run方法;
3、在SpringApplication构造器中调用initialize(sources)方法;
4、在initialize方法中:
a、将sources转换成list加到this.sources属性中;
b、判断是否为Web环境(在类路径下是否可以加载到Servlet和ConfigurableWebApplicationContext);
c、加载initializers(通过META-INF/spring.factories中键为 ApplicationContextInitialzer的配置进行加载),debug发现一共加载了6个initializer(spring-boot-1.5.10.RELEASE.jar中四个,autoconfigure-1.5.10-RELEASE.jar中两个);
d、加载ApplicationListener(也是通过META-INF/spring.factories),debug发现共加载了10个;
e、通过寻找main方法找到主启动类;
5、run方法中
a、StopWatch主要时监控启动过程,统计启动时间,检测应用是否已启动或者停止;
b、加载SpringApplicationRunListener(也是通过META-INF/spring.factories),默认加载的是EventPublishingRunListener;
c、调用RunListener.starting()方法;
d、根据args创建应用参数解析器ApplicationArguments;
e、准备环境变量:获取环境变量environment,将应用参数放入到环境变量持有对象中,监听监听器环境变量对象的变化;(listener.environmentPrepared)
f、打印Banner信息;(SpringBootBanner)
g、创建SpringBoot的应用上下文(AnnotationConfigEmbeddedWebApplicationContext)
h、prepareContext 上下文之前的准备;
i、refreshContext刷新上下文;
j、afterRefresh(ApplicationRunner,CommandLineRunner 接口实现类的启动);
k、返回上下文对象;
15、AOP和IOC采用的设计模式?
aop:代理模式;
ioc:工厂模式;
16、在分布式系统中如何合并多个服务的日志?(每个日志文件大小约300M,合并成一个日志文件)
使用归并算法,可以为每个文件分配一个40M的数组,再另外分配一个400M的数组存储归并结果,每个文件每次读取40M,对十个数组做归并排序直到其中某个数组的数据被处理完,这时将归并结果写入磁盘,处理完的数组继续读入40M,继续参与归并,以此类推,直到所有文件都处理完。
17、HashMap链表转为红黑树,为什么一定要链表长度为8的时候呢?7、9它不可以吗?
选择8是从时间复杂度考虑的,从8开始用树效率更好;红黑树的平均查找长度,也就是时间复杂度log(n),长度为8,查找长度log(8)=3,因为2的三次方是8;链表的平均查找为n/2,当长度为8时,平均查找长度为8/2=4,这时才有转换成树的必要,因为log(8)比8/2小,用树结构需要的查找步数更小。
18、HashMap扩容,为什么是以2的幂次方增长,不是3、4?
HashMap计算添加元素的位置时,使用的是位运算,这是特别高效的运算;另外,HashMap的初始容量是2的n次幂,扩容也是2倍的形式进行扩容,是因为容量是2的n次幂,只需要判断高位hash,移动到之前到位置的倍数就可以了,免去了重新计算位置的运算,可以使得添加的元素均匀分布在HashMap中的数组上,减少hash碰撞,避免形成链表的结构,使得查询效率降低。
19、HashMap初始化容量设置多少合适?如果设置为7,其容量是多少?
当我们使用HashMap(int initialCapacity)来初始化容量的时候,HashMap并不会使用我们传进来的initialCapacity 值直接作为初始容量;JDK会默认帮我们计算一个相对合理的值当作初始容量,就是找到第一个比用户传入的值大的2的幂;如当我们new HashMap(7)创建HashMap的时候,JDK会通过计算,帮我们创建一个容量为8(2的三次幂)的Map;当我们new HashMap(9)创建HashMap的时候,DK会通过计算,帮我们创建一个容量为16(24)的Map。所以,可以根据业务需求来给HashMap设置一个初始化容量,如果明确知道一个HashMap的容量为7时,可以通过newHashMapWithExpectedSize(7)创建HashMap;
Map<String,String> map = Maps.newHashMapWithExpectedSize(7);
通过该方法创建Map就不会导致HashMap自动扩容,影响性能,是一种用内存换性能的做法。
20、锁的底层原理?为什么能够锁住?
1、synchronized是通过监视器锁(monitor)实现的;
2、Lock底层是通过AQS实现的,采用线程独占的形式,在硬件层面依赖特殊的CPU指令(CAS);简单来说ReenTrantLock的实现是一种自旋锁,通过循环调用CAS操作来实现枷锁;
3、在JVM底层volatile是采用“内存屏障”来实现的。
21、Mybatis的二级缓存及原理?
Mybatis默认开启一级缓存,支持在同一个会话(sqlsession)同一个statement执行两次,则第二次会默认使用第一次创建的缓存对象;一级缓存是sqlsession级别、二级缓存是Mapper级别;Mybatis在为SqlSession对象创建Executor对象时,会对Executor对象加上一个装饰者:CachingExecutor,这时SqlSession使用CachingExecutor对象来完成操作请求CachingExecutor对于查询请求,会先判断该查询在Application级别的二级缓存中是否有缓存结果,如果有查询结果,则直接返回缓存结果;如果缓存中没有,再交给真正的Executor对象来完成查询操作,之后CachingExecutor会将真正Executor返回的查询结果放置到缓存中,然后再返回给用户;CachingExecutor是Executor的装饰者,以增强Executor的功能,使其具有缓存查询功能,这里用到了设计模式中的装饰者模式。
22、既然红黑树这么好,为什么不一开始就直接用红黑树代替链表?
因为红黑树需要左旋、右旋操作,而单链表不需要;当个数不多的时候,直接遍历更方便,实现起来也简单,而红黑树的实现要复杂的多。
为了不死,我愿献出生命