目录
1. ArrayList和LinkedList的区别,就是我在插入和删除的时候他们在时间复杂度上有什么区别
10. 假设现在有两个线程,一个线程把这个值改成false,另一个线程是立刻可见的吗
11. 具体Java内存模型怎么指定的另一个线程对一个线程修改的值何时可见,如何可见的
14. 我设置了一个代码块或变量我怎么做可以让这个强制不会被系统回收
18. 这个功能里面,里面的排序怎么实现的,就是把数据也就是score放进去,redis如何给你排序的,就是低层算法
23. udp是一个不可靠的,就是会丢包,但是我想要udp不丢包,可靠传输怎么处理
25. 可以介绍一下虚拟内存是什么意思吗,就是操作系统里的虚拟内存
26. 我在程序里面六了一个对象,这个对象什么时候会变成虚拟内存
34. 常见的,什么情况下会导致栈溢出,就是你使用什么方法,怎么做,可以导致栈溢出
一面
1. ArrayList和LinkedList的区别,就是我在插入和删除的时候他们在时间复杂度上有什么区别
ArrayList
:基于数组实现,在中间或开头插入和删除元素时,需要移动后续元素,时间复杂度为O(n);在尾部插入和删除元素,如果不涉及扩容,时间复杂度为O(1)。LinkedList
:基于双向链表实现,在任意位置插入和删除元素,只需要修改相邻节点的指针,时间复杂度为O(1);但如果要定位到指定位置进行插入或删除,需要从头或尾遍历链表,时间复杂度为O(n)。
2. hashmap在java的底层是怎么实现的
在 Java 中,HashMap
底层是数组 + 链表 + 红黑树的结构。
- 数组:也叫哈希桶,每个位置存储一个链表或红黑树的头节点。
- 链表:当多个键的哈希值相同时,会以链表的形式存储在同一个哈希桶中。
- 红黑树:当链表长度超过 8 且数组长度大于 64 时,链表会转换为红黑树,以提高查找效率。
- 当红黑树的节点数量减少到 6 时,红黑树会转换回链表。
3. 红黑树的实现原理
红黑树是一种自平衡的二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色(红色或黑色)。通过对任何一条从根到叶子的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。
插入和删除操作后,会通过旋转和变色操作来维持红黑树的平衡。
4. 红黑树的特点
- 每个节点要么是红色,要么是黑色。
- 根节点是黑色。
- 每个叶子节点(NIL 节点,空节点)是黑色的。
- 如果一个节点是红色的,则它的两个子节点都是黑色的。
- 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
5. 为什么红黑树比链表查询速度快
链表的查询需要从头节点开始逐个遍历,时间复杂度为O(n)。而红黑树是一种二叉搜索树,它的查找操作类似于二分查找,时间复杂度为O(logn),因此在数据量较大时,红黑树的查询速度更快。
6. 在java中字符串的操作方式有几种
- 使用
String
类:String
类是不可变的,每次对String
对象进行操作都会创建一个新的String
对象。 - 使用
StringBuilder
类:StringBuilder
是可变的,非线程安全,适合在单线程环境下进行字符串拼接等操作。 - 使用
StringBuffer
类:StringBuffer
也是可变的,但它是线程安全的,适合在多线程环境下进行字符串操作。
7. StringBuffer是怎么保证线程安全性的
StringBuffer
类的方法都使用了synchronized
关键字进行修饰,这意味着在同一时间只能有一个线程访问这些方法,从而保证了线程安全。
8. Java字符串的常量池
Java 字符串常量池是一个特殊的内存区域,用于存储字符串常量。当创建一个字符串常量时,JVM 会先检查常量池中是否已经存在该字符串,如果存在则直接返回常量池中的引用,否则会在常量池中创建一个新的字符串对象。
9. volitite这个关键字有了解过吗
volatile
关键字用于保证变量的可见性,即当一个变量被声明为volatile
时,它会保证对该变量的写操作会立即刷新到主内存中,而读操作会从主内存中读取最新的值。
10. 假设现在有两个线程,一个线程把这个值改成false,另一个线程是立刻可见的吗
如果一个变量被声明为volatile
,当一个线程把这个值改成false
时,另一个线程会立刻可见。因为volatile
关键字保证了变量的可见性,写操作会立即刷新到主内存,读操作会从主内存中读取最新的值。
11. 具体Java内存模型怎么指定的另一个线程对一个线程修改的值何时可见,如何可见的
Java 内存模型(JMM)通过happens-before
原则来保证线程之间的可见性。如果一个操作happens-before
另一个操作,那么第一个操作的结果对第二个操作是可见的。常见的happens-before
规则包括:
- 程序顺序规则:一个线程中的每个操作,
happens-before
该线程中的任意后续操作。 - 监视器锁规则:对一个锁的解锁,
happens-before
随后对这个锁的加锁。 volatile
变量规则:对一个volatile
域的写,happens-before
任意后续对这个volatile
域的读。- 线程启动规则:
Thread.start()
方法happens-before
此线程的每个一个动作。 - 线程终止规则:线程中的任何操作都
happens-before
其他线程检测到这个线程已经终止。 - 中断规则:一个线程调用另一个线程的
interrupt()
方法happens-before
被中断线程的代码检测到中断事件的发生。 - 对象终结规则:一个对象的初始化完成(构造函数执行结束)
happens-before
它的finalize()
方法的开始。
12. hashmap的时间查找复杂度是多少
在理想情况下,HashMap
的查找时间复杂度为O(1),因为可以通过哈希函数直接定位到对应的哈希桶。但在最坏情况下,即所有键的哈希值都相同,链表退化为线性结构,查找时间复杂度为O(n)。在使用红黑树优化后,最坏情况下的查找时间复杂度为O(log n)。
13. Java的内存管理和回收有了解过吗
Java 的内存管理主要由 JVM 负责,包括内存分配和内存回收。
- 内存分配:对象通常在堆上分配,基本数据类型和对象引用可能在栈上分配。
- 内存回收:JVM 使用垃圾回收器(GC)来自动回收不再使用的对象所占用的内存。常见的垃圾回收算法包括标记 - 清除算法、标记 - 整理算法、复制算法等。
14. 我设置了一个代码块或变量我怎么做可以让这个强制不会被系统回收
在 Java 中,无法强制让一个对象不被系统回收。但可以通过持有对象的强引用,避免对象被垃圾回收。例如,将对象存储在一个静态变量中,或者在一个长期存活的对象中持有该对象的引用。
15. 对象如何从新生代到老年代的
对象通常首先在新生代的 Eden 区分配内存。当 Eden 区满时,会触发 Minor GC,存活的对象会被移动到 Survivor 区。经过多次 Minor GC 后,仍然存活的对象会被移动到老年代。此外,如果对象的大小超过了新生代的阈值,也会直接在老年代分配内存。
16. 你对快排有了解过吗?比如如何排序的,流程
快速排序是一种分治算法,其基本流程如下:
- 选择一个基准元素(pivot)。
- 将数组分为两部分,使得左边部分的元素都小于等于基准元素,右边部分的元素都大于等于基准元素。
- 递归地对左右两部分进行快速排序。
17. redis实现排行榜,底层如何实现的
Redis 使用有序集合(Sorted Set)来实现排行榜。有序集合中的每个成员都有一个分数(score),Redis 会根据分数对成员进行排序。
- 底层数据结构:有序集合使用跳跃表(Skip List)和哈希表(Hash Table)实现。跳跃表用于实现按分数排序,哈希表用于快速查找成员。
- 排序算法:Redis 使用跳跃表的插入和删除操作来维护有序集合的顺序,时间复杂度为\(O(log n)\)。
18. 这个功能里面,里面的排序怎么实现的,就是把数据也就是score放进去,redis如何给你排序的,就是低层算法
19. 有没有了解过redis的缓存穿透和击穿
- 缓存穿透:指查询一个不存在的数据,由于缓存中没有该数据,会直接查询数据库,导致数据库压力过大。解决方法包括使用布隆过滤器、缓存空值等。
- 缓存击穿:指某个热点数据在缓存中过期,此时大量请求同时访问该数据,会直接查询数据库,导致数据库压力过大。解决方法包括使用互斥锁、设置热点数据永不过期等。
20. 介绍一下tcp和udp区别
- 连接性:TCP 是面向连接的,在传输数据之前需要建立连接;UDP 是无连接的,不需要建立连接。
- 可靠性:TCP 提供可靠的数据传输,通过确认机制、重传机制等保证数据的完整性;UDP 不保证数据的可靠传输,可能会出现丢包、乱序等问题。
- 传输效率:TCP 的传输效率相对较低,因为需要建立连接、维护状态等;UDP 的传输效率相对较高,因为不需要建立连接。
- 应用场景:TCP 适用于对可靠性要求较高的场景,如文件传输、网页浏览等;UDP 适用于对实时性要求较高的场景,如视频直播、游戏等。
21. http和tcp有啥关系
HTTP 是应用层协议,TCP 是传输层协议。HTTP 协议基于 TCP 协议进行数据传输,HTTP 请求和响应通过 TCP 连接进行发送和接收。
22. http本身有三次握手吗
HTTP 本身没有三次握手,三次握手是 TCP 协议在建立连接时进行的操作。HTTP 请求和响应是在 TCP 连接建立之后进行的。
23. udp是一个不可靠的,就是会丢包,但是我想要udp不丢包,可靠传输怎么处理
可以通过在应用层实现一些机制来让 UDP 可靠传输,例如:
- 确认机制:发送方发送数据后,等待接收方的确认信息,如果在一定时间内没有收到确认信息,则重传数据。
- 序号机制:为每个数据包分配一个序号,接收方根据序号对数据包进行排序,确保数据的顺序性。
- 超时重传机制:发送方设置一个超时时间,如果在超时时间内没有收到确认信息,则重传数据。
24. 那我怎么知道对方已经和我断开了连接了还是
在 TCP 连接中,可以通过以下方式判断对方是否断开连接:
- 接收方收到 FIN 包:当对方关闭连接时,会发送一个 FIN 包,表示不再发送数据。
- 心跳机制:定期发送心跳包,检查对方是否还在正常工作。如果在一定时间内没有收到对方的响应,则认为对方已经断开连接。
25. 可以介绍一下虚拟内存是什么意思吗,就是操作系统里的虚拟内存
虚拟内存是操作系统为每个进程提供的一种抽象的内存管理机制。它将进程的地址空间分为多个页面,每个页面可以映射到物理内存中的一个页框,也可以映射到磁盘上的交换空间。通过虚拟内存,操作系统可以让进程使用比物理内存更大的地址空间。
26. 我在程序里面六了一个对象,这个对象什么时候会变成虚拟内存
当物理内存不足时,操作系统会将一些不常用的页面交换到磁盘上的交换空间,这些页面对应的对象就变成了虚拟内存。当进程需要访问这些页面时,操作系统会将它们从磁盘上交换回物理内存。
27. 何时去物理内存里
当物理内存不足时,操作系统会将一些不常用的页面交换到磁盘上的交换空间,这些页面对应的对象就变成了虚拟内存。当进程需要访问这些页面时,操作系统会将它们从磁盘上交换回物理内存。
28. 介绍一下堆和栈的区别
- 存储内容:堆主要用于存储对象和数组,栈主要用于存储局部变量、方法调用信息等。
- 内存分配方式:堆的内存分配是动态的,由垃圾回收器负责回收;栈的内存分配是静态的,由编译器自动分配和释放。
- 线程共享性:堆是所有线程共享的,栈是每个线程独立拥有的。
29. 什么变量会在栈里面
局部变量、方法参数、方法调用的上下文信息等会存储在栈中。
30. 方法运行的时候是在堆里面还是栈里面
方法的执行过程中,方法的局部变量、方法调用信息等会存储在栈中,而方法中创建的对象会存储在堆中。
31. 一个对象会在堆里面还是栈里
对象通常存储在堆中,但在某些情况下,对象可能会被分配到栈上,例如逃逸分析优化。
32. 什么情况下会在栈里面
当对象的作用域仅限于方法内部,并且不会逃逸到方法外部时,JVM 可能会对对象进行逃逸分析,如果发现对象不会逃逸,就可以将对象分配到栈上,这样可以减少垃圾回收的压力。
33. 怎么判断是临时使用的对象
临时使用的对象通常是指作用域仅限于某个方法内部,并且在方法执行结束后就不再使用的对象。可以通过对象的引用是否会逃逸到方法外部来判断对象是否是临时使用的。
34. 常见的,什么情况下会导致栈溢出,就是你使用什么方法,怎么做,可以导致栈溢出
栈溢出通常是由于方法调用的深度过深,导致栈空间不足。常见的导致栈溢出的情况包括:
- 递归调用没有终止条件或终止条件不正确。
- 方法调用链过长,例如在一个方法中不断调用其他方法。
35. 算法题,删除链表倒数第3个节点
使用了双指针
36. 我想看linux下还剩下多少内存,我用啥命令
free -h
37. 你常用的,用过的命令有哪些,他们的作用是什么
ls
:列出目录中的文件和子目录。cd
:切换当前工作目录。mkdir
:创建新的目录。rm
:删除文件或目录。cp
:复制文件或目录。mv
:移动或重命名文件或目录。cat
:查看文件内容。grep
:在文件中查找指定的字符串。ps
:查看当前运行的进程。top
:实时监控系统的资源使用情况。
38. 我要编辑文件用什么命令
在 Linux 中,可以使用vim
或nano
等命令来编辑文件。
39. Vim和vi的区别
Vim
是vi
的增强版本,Vim
在vi
的基础上增加了许多新的功能,例如语法高亮、代码折叠、多窗口编辑等。在大多数 Linux 系统中,vi
实际上是vim
的一个别名。
二面
深挖项目,应用场景,高并发,分布式
近日总结:目前来看,一周4个面试,挺不错的。