java面试(进阶三篇)解答

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26323323/article/details/83751298

题目来自于网络,答案是笔者整理的。仅供参考,欢迎指正

来源: https://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247485723&idx=1&sn=f5c3bfbfab9fe01e6d4979e4f315f024&chksm=e9c5f0aadeb279bcff0b81842f09adc1bbf0f4d2b7bb74c5b1c4749bd1bc837e76330c81cc08&scene=21&key=f02705432716b525abb21bf4b72b95d535c372bcd26a437e05deeec7eb0c79966fd85e831802f94d715c009e49871cafb21d20ca7710a496de84350b78db9317b8b4cc6562a9eed840776d9510a4b819&ascene=7&uin=MjM2OTQ3MDkzOQ%3D%3D&devicetype=Windows+7&version=6206021b&lang=zh_CN&pass_ticket=h97v%2FevjbeMS22Cec6mLcTFMVU17Iq0u%2FWtXpCY668m3AU7lLNOkKa9JdWj%2B8omE&winzoom=1

一、基础题

  • 怎么解决Hash冲突;(开放地址法、链地址法、再哈希法、建立公共溢出区等)

  • 写出一个必然会产生死锁的伪代码;

  • Spring IoC涉及到的设计模式;(工厂模式、单利模式。。)

  • toString()方法什么情况下需要重写;

  • 判断对象相等时,什么情况下只需要重写 equals(),什么情况下需要重写 equals(),hashcode()?

  • Set内存放的元素为什么不可以重复,内部是如何保证和实现的?

  • 如何保证分布式缓存的一致性(分布式缓存一致性hash算法?)?分布式session实现?

  • Java 8流式迭代的好处?

  • 项目中用到的JDK的哪些特性?

  • 说一下TreeMap的实现原理?红黑树的性质?红黑树遍历方式有哪些?如果key冲突如何解决?setColor()方法在什么时候用?什么时候会进行旋转和颜色转换?

  • Spring的bean的创建时机?依赖注入的时机?

  • ArrayList和LinkList的删除一个元素的时间复杂度;(ArrayList是O(N),LinkList是O(1));

  • CopyOnWriteArrayList是什么;

  • 序列化和反序列化底层如何实现的(ObjectOutputStream 、ObjectInputStream、 readObject  writeObject);

  • 如何调试多线程的程序;

  • 一个线程连着调用start两次会出现什么情况?(由于状态只有就绪、阻塞、执行,状态是无法由执行转化为执行的,所以会报不合法的状态!)

  • HashMap在什么时候时间复杂度是O(1),什么时候是O(n),什么时候又是O(logn);

  • wait方法能不能被重写?(wait是final类型的,不可以被重写,不仅如此,notify和notifyall都是final类型的),wait能不能被中断;

  • 一个Controller调用两个Service,这两Service又都分别调用两个Dao,问其中用到了几个数据库连接池的连接?

二、网络基础

  • HTTP、TCP、UDP的区别和联系;

  • TCP和UDP各自的优势,知道哪些使用UDP协议的成功案例;

  • TCP和UDP各用了底层什么协议;

  • 单个UDP报文最大容量;

  • 单个TCP报文最大容量;

  • TCP报头格式、UDP报头格式;

  • Server遭遇SYN Flood应当怎么处理;

  • Web开发中如何防范XSS?

  • 拆包和粘包的问题,如何解决,如果我们的包没有固定长度的话,我们的应用程序应该如何解决;

三、操作系统

  • 为什么要内存对齐;

  • 为什么会有大端小端,htol这一类函数的作用;

  • top显示出来的系统信息都是什么含义;(重要!)

  • Linux地址空间,怎么样进行寻址的;

  • Linux如何查找目录或者文件的;

四、分布式其他

  • 分库与分表带来的分布式困境与应对之策;

  • Solr如何实现全天24小时索引更新;

五、Redis

  • Redis插槽的分配(key的有效部分使用CRC16算法计算出哈希值,再将哈希值对16384取余,得到插槽值);

  • Redis主从是怎么选取的(一种是主动切换,另一种是使用sentinel自动方式);

  • Redis复制的过程;

  • Redis队列应用场景;

  • Redis主节点宕机了怎么办,还有没有同步的数据怎么办;

六、系统设计开放性题目

  • 秒杀系统设计,超卖怎么搞;

  • 你们的图片时怎么存储的,对应在数据库中时如何保存图片的信息的?

  • 假如成都没有一座消防站,现在问你要建立几座消防站,每个消防站要配多少名消防官兵,多少辆消防车,请你拿出一个方案;

  • 基于数组实现一个循环阻塞队列;

  • 常见的ipv4地址的展现形式如“168.0.0.1”,请实现ip地址和int类型的相互转换。(使用位移的方式)

  • 现网某个服务部署在多台Liunx服务器上,其中一台突然出现CPU 100%的情况,而其他服务器正常,请列举可能导致这种情况发生的原因?如果您遇到这样的情况,应如何定位?内存?CPU?发布?debug?请求量?

七、大数据量问题(后边会有专题单独讨论)

  • 给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?

  • 海量日志数据,提取出某日访问百度次数最多的那个IP;

  • 一个文本文件,大约有一万行,每行一个词,要求统计出其中最频繁出现的前10个词,请给出思想,给出时间复杂度分析。

此话题后边会有专门的文章探讨,如果有等不及的小伙伴,可以移步参考:

1、https://blog.csdn.net/v_july_v/article/details/6279498

2、https://blog.csdn.net/v_july_v/article/details/7382693

八、逻辑思维题

  • 有两根粗细均匀的香(烧香拜佛的香),每一根烧完都花一个小时,怎么样能够得到15min?

  • 假定你有8个撞球,其中有1个球比其他的球稍重,如果只能利用天平来断定哪一个球重,要找到较重的球,要称几次?(2次);

  • 实验室里有1000个一模一样的瓶子,但是其中的一瓶有毒。可以用实验室的小白鼠来测试哪一瓶是毒药。如果小白鼠喝掉毒药的话,会在一个星期的时候死去,其他瓶子里的药水没有任何副作用。请问最少用多少只小白鼠可以在一个星期以内查出哪瓶是毒药;(答案是10只)

  • 假设有一个池塘,里面有无穷多的水。现有2个空水壶,容积分别为5升和6升。问题是如何只用这2个水壶从池塘里取得3升的水;

参考答案

一、基础题

1.怎么解决Hash冲突

    

    * 开放定址法(也称为再散列法,基本思想是:当关键字key的哈希地址p出现冲突时,以p为基础,产生另一个地址p1,如果p1仍然冲突,则再以p为基础,产生另一个地址p2..直到不再冲突)。主要有以下三种方法:

        * 线性探测再散列(发生冲突时,顺序查看下一个单元,直到出现空单元)

        * 二次探测再散列(发生冲突时,在表的左右跳跃式探测)

        * 伪随机探测

    * 再哈希法(同时构造多个不同的哈希函数,当某一个函数构造的哈希地址发生冲突时,再计算别的函数)

    * 链地址法(将所有哈希地址为i的元素构成一个称为同义词链的单链表)适用于经常添加和删除的操作

    * 建立公共溢出区(将哈希表分为基本表和溢出表,凡是和基本表冲突的,一律填入溢出区)

    更多请参考:https://www.cnblogs.com/wuchaodzxx/p/7396599.html  

2.写出一个必然会产生死锁的伪代码

private static final Object a = new Object();
private static final Object b = new Object();

public void handleA(){
 synchronized(a){
     // doSomething...
     synchronized(b){
     // doSomething...
     }
 }   
}

public void handleB(){
 synchronized(b){
     // doSomething...
     synchronized(a){
     // doSomething...
     }
 }   
}

3.Spring IoC涉及到的设计模式

    简单工厂模式、单例模式

4.toString()方法什么情况下需要重写

    默认使用的是Object.toString()方法,具体内容如下:

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

    不需要使用类的具体信息的时候就不需要重写

5.判断对象相等时,什么情况下只需要重写 equals(),什么情况下需要重写 equals(),hashcode()

    两个对象比较,调用equals方法进行比较时,默认比较的是两个对象是否指向同一块内存地址,如果是则相等,否则不相等。

    如果想修改这种规则,即只比较对象的某些属性是否相等的时候,那么则需要重写equals方法。

    一般来说,重写equals方法必须也重写hashcode方法

6.Set内存放的元素为什么不可以重复,内部是如何保证和实现的

    我们以hashSet为例,hashSet实际是使用hashmap来实现的,hashSet的值作为hashmap的key,value为定值。我们可以通过分析hashMap的put过程来分析hashSet是如何不重复的。

    我们知道hashMap是哈希表+链表的方式来实现的。通过key的hashCode来确定在哈希表中的index,相同的key会定位到同一个index,下面就是存放Entry,entry包含key和value,会将当前key与链表中的元素的key逐个比较,如果都不相等则放置到链表头;如果存在相等的,则重置entry的value值为当前value

    通过上面的过程分析可知,由于hashSet使用hashMap实现时,value值都是定值,所以不会存在相同元素

7.如何保证分布式缓存的一致性

    分布式一致性hash算法

8.Java 8流式迭代的好处

    * 代码更简洁

    * 提供并行流式计算,在处理集合较大时,parallelStream()极大提高效率

    ...

9.项目中用到的JDK的哪些特性

    项目中使用jdk8,回答jdk8的一些新特性

Lambda 表达式 − Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中。
方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。
新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
Date Time API − 加强对日期与时间的处理。
Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。

10.说一下TreeMap的实现原理?红黑树的性质?红黑树遍历方式有哪些?如果key冲突如何解决?setColor()方法在什么时候用?什么时候会进行旋转和颜色转换?

    // TODO

11.Spring的bean的创建时机?依赖注入的时机?

    在默认情况下,启动spring容器的时候创建对象,同时对所依赖的对象进行注入

    如果配置bean的lazy-init属性为true,在context.getBean()时才创建对象

12.ArrayList和LinkList的删除一个元素的时间复杂度

    * ArrayList O(N)

    * LinkedList O(1)

13.CopyOnWriteArrayList是什么

    并发安全版本的ArrayList

14.序列化和反序列化底层如何实现的

    序列化:把java对象转换为字节序列的过程(对象序列化最主要的作用就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化后的字节流保存了java对象的转状态以及相关的描述信息)

    反序列化:将字节序列恢复为java对象的过程(客户端从文件或网络上获取序列化后的对象字节流后,根据字节流中保存的对象状态和描述信息,通过反序列化重建对象)

    序列化算法的操作步骤:

    * 将对象的类元数据输出

    * 递归输出类的超类描述直到不再有超类

    * 类元数据完成以后,开始从最顶层的超类输出对象实例的实际值

    * 从上到下递归输出实例的数据

    延伸:为什么要主动定义serialVersionUID,其作用是什么?

    需要序列化的对象需要主动实现Serializable接口,这个接口是一个标记接口,IDE会提示我们需要主动生成一个serialVersionUID,如果我们不主动生成的话,那么IDE会在我们序列化对象的时候主动帮我们生成一个。

    那么其作用是什么呢?我们先看一个示例

// 1.写一个Account类
public class Account implements Serializable {
	private int id;
	private String name;
}

// 2.使用ObjectOutputStream将Account实例保存到一个文件
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File("C:/Users/Administrator/Desktop/test1.txt")));
objectOutputStream.writeObject(new Account(1,"jack"));

// 3.修改Account类,添加一个属性
	private int age;

// 4.这时再使用ObjectInputStream将test1.txt文件反序列化成Account对象
// 报错信息如下:
java.io.InvalidClassException: cache.Account; local class incompatible: stream classdesc serialVersionUID = -3122741699590248598, local class serialVersionUID = -8634529858385187253

    将上述过程重复一遍,不同点就是创建Account类的时候主动生成一个serialVersionUID,如下所示:

public class Account implements Serializable {
	private static final long serialVersionUID = 1L;
	private int id;
	private String name;

    此时保存后再反序列化成Account对象,可以发现,没有报错,Account对象成功打印

    总结:当我们修改了我们的类的时候,那么当前类的默认的serialVersionUID就会改变,和以前序列化到本地的serialVersionUID不同,那么这时候反序列文件的时候就会报错

15.如何调试多线程的程序

    可使用JDI来调试

    具体用法可参考:https://m.vipcn.com/a/332165/ 

16.一个线程连着调用start两次会出现什么情况?

    第二次线程会报错,报错内容如下:

Exception in thread "main" java.lang.IllegalThreadStateException
	at java.lang.Thread.start(Thread.java:708)
	at javacore.mulit.MyThread.main(MyThread.java:40)

    第一次调用start之后,threadStatus会改变(非0,0代表新建),所以第二次在调用会报错

17.HashMap在什么时候时间复杂度是O(1),什么时候是O(n),什么时候又是O(logn)

    O(1):当map中的元素哈希码都不冲突的时候,会均匀分配在数组中

    O(n):当map中的元素哈希码都冲突的时候,实际上就变成了一个链表结构的数据

    O(logn):map中的元素有部分冲突

18.wait方法能不能被重写?

    wait方法属于Object类,是final类型的,所以不能重写,源码如下:

public final void wait() throws InterruptedException {
    wait(0);
}

19.一个Controller调用两个Service,这两Service又都分别调用两个Dao,问其中用到了几个数据库连接池的连接?

    // TODO

未完待续...

猜你喜欢

转载自blog.csdn.net/qq_26323323/article/details/83751298
今日推荐