java面试(八股文)
2021-08-15 09:18:50 0 举报
AI智能生成
登录查看完整内容
面试
作者其他创作
大纲/内容
堆,栈,Program Counter,元空间
内存模型
java怎么进行垃圾回收的?什么对象会进老年代?
年轻代不足以分配对象,老年代不足以分配年轻代晋升的对象
什么时候会触发GC
Java虚拟机内存模型
有哪些对象可以作为GC Root
new一个对象会触发哪些操作
内存回收算法
如何判断对象被回收
什么情况下会产生Full GC
垃圾回收的算法有哪些?为什么新生代使用复制算法?
JVM
Lambda 表达式 : Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。方法引用:可以直接引用已有Java类或对象(实例)的方法或构造器。默认方法 :默认方法就是一个在接口里面有了一个实现的方法。Stream API :新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。Date Time API:加强对日期与时间的处理。Optional 类 :Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常
JDK8 的新特性
怎么用两个栈实现队列
怎么检测链表的环
如何判断一个链表是否有环
判断镜像二叉树
接雨水问题
算法
aes和md5的区别
数据安全
树是由根结点和若干颗子树构成的。树是由一个集合以及在该集合上定义的一种关系构成的。红黑树(Red Black Tree)是一颗自平衡(self-balancing)的二叉排序树(BST),树上的每一个结点都遵循下面的规则(特别提醒,这里的自平衡和平衡二叉树AVL的高度平衡有别):每一个结点都有一个颜色,要么为红色,要么为黑色;树的根结点为黑色;树中不存在两个相邻的红色结点(即红色结点的父结点和孩子结点均不能是红色);从任意一个结点(包括根结点)到其任何后代 NULL 结点(默认是黑色的)的每条路径都具有相同数量的黑色结点。
大多数的排列的二叉树的操作复杂度都是O(h) ->h指的是树的高度,但是红黑树的操作复杂度只有O(logn)
为什么要有红黑树?
AVL二叉树比红黑树更平衡,但是也要区分情况,如果插入和删除比较多的话,存在很多旋转的操作,就用红黑树,如果查询比较频繁的话,就用AVL平衡二叉树
红黑树RBT与平衡二叉树AVL比较
1.java中的TreeMap和TreeSet2.linux中cpu的完全公平调度
红黑树有什么应用
是根据插入节点的hash值进行比较
红黑树需要比较大小才能进行插入,是依据什么进行比较的?
二叉树的概念?红黑树又是什么,红黑树和其他平衡树的区别在哪
1.因为hash值只能匹配是否相等,不能范围搜索,原来是键值对,在经过哈希算法之后,有可能就变成不连续的,就不能通过索引来进行范围搜索2.当按照索引进行order by的时候,hash值没办法支持排序,因为hash值散性的特性,无法利用索引进行排序3.当数据量很大的时候,hash冲突的概率也很大,特别是在有大量重复键值的情况下,哈希索引的效率是非常低的,因为存在哈希碰撞问题。
数据库索引为什么使用B+树而不是hash索引
相当于多叉树,又叫平衡多路查找树,数据库索引中大量使用了B树和B+树
B树
概念B+树是B树的一个升级版,相对于B树来说B+树更充分的利用了节点的空间,让查询速度更加稳定,其速度完全接近于二分法查找。为什么说B+树查找的效率要比B树更高、更稳定;我们先看看两者的区
hash和B+树的区别?分别应用到什么场景?哪个比较好?
B+树
与B+树的区别是1.关键个数限制问题--B+树初始化的关键个数是cei(m/2)B*树初始化参数的关键个数是cei(2/3m)2.B+树存满的时候就会分裂,但是B*树会判断兄弟节点是否存满,如果不满的话,则向兄弟节点转移关键字,如果存满的话,就向当前的节点和兄弟节点各拿出1/3的数据创建一个新的节点
B*树
1.无论是什么树,都是采用二分法和数据平衡策略来提升数据查询速率
2.在不同的空间分配上-->他们这些树都是一步一步的演变过程中通过IO从磁盘读取数据的原理进行演变,每一次演变都是更合理的利用磁盘空间和减少树的层次来提升查询数据的速度
B树总结
考察到一个节点后,即刻输出该节点的值,并继续遍历其左右子树
先序:根左右
考察到一个节点后,将其暂存,遍历完左子树后,再输出该节点的值,然后遍历右子树。
中序:左右根
考察到一个节点后,将其暂存,遍历完左右子树后,再输出该节点的值
后序:左右根
先序,中序、后序遍历
二叉树的层序遍历
树
数组的下标就是 (n-1)&hash
底层实现
底层数组+链表实现,可以存储null键和null值,线程不安全
hashtable和concurrenthashmap区别,底层实现
什么时候用hashMap,什么情况用ConcurrentHashMap?
是否线程安全,会导致什么问题(不是,会导致更新丢失,比如balabala)
为什么会有线程安全问题?
除了更新丢失,HashMap还会造成什么问题,1.7和1.8的区别?(1.7头插入会导致死循环,1.8改用尾插法)
会发生hash碰撞,当key相等的时候,旧的value会被替换,否则的话加入到链表的后面,但是当链表的阈值大于8,数组的长度超过64,会转为红黑树,java1.7之前是头插法,1.8是尾插法
当两个对象的hashCode值相等时会发生什么?
HashMap 是基于哈希表实现的,每一个元素是一个键值对,其内部通过单链表或者红黑树解决冲突问题,容量不足(超过了阀值)时,会自动扩容。HashMap是非线程安全的,只适用于单线程环境,多线程环境可以采用并发包下的concurrentHashMap。HashMap 实现了Serializable接口,因此它支持序列化,实现了Cloneable接口,能被克隆。HashMap是基于哈希表的 Map 接口的非同步实现,此实现提供所有可选的映射操作,并允许使用 null 值和 null 键,此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashMap 每次扩容都是建立一个新的 table 数组,长度和容量阈值都变为原来的两倍,然后把原数组元素重新映射到新数组上,具体步骤如下:首先会判断 table 数组长度,如果大于 0 说明已被初始化过,那么按当前 table 数组长度的 2 倍进行扩容,阈值也变为原来的 2 倍;如果旧数组容量已经是最大值了,那只需把 threshold 阈值设为整数的最大值即可;若 table 数组未被初始化过,且 threshold(阈值)大于 0 说明调用了 有参构造方法,那么就把数组大小设为 threshold;若table 数组未被初始化,且 threshold 为 0 说明调用无参构造方法,那么就把数组大小设为16,threshold 设为 16*0.75;接着需要判断如果不是第一次初始化,那么扩容之后,要重新计算键值对的位置,并把它们移动到合适的位置上去,如果节点是红黑树类型的话则需要进行红黑树的拆分。
因为(n-1)&hash后得到的结果(下标)是均匀的
为什么?
底层有一个方法tableSizeFor(int cap)通过移运算和或运算得到一个容量比传入的initialCapacity大的最小的2的次幂数,并将其作为HashMap的初始容量。例如传入7得到初始容量为8的HashMap,传入9得到初始容量为16的HashMap。会自动把它变为2的幂次方
如果初始值不是2的幂次方咋办?
初始容量是2的幂次方
默认容量是数组大小为16,扩展因子是0.75,所以16*0.75=12,证明当数组中的大小超过12的时候,这个时候就会扩容
HashMap的初始容量是多少?
时间复杂度
HashMap中Hash冲突怎么解决的
HashMap首先有一个hashCode方法,获取key的hashcode值h,然后将这个h右移16位获取h的高16位,与之前的低十六位进行异或,返回的值与(数组size-1)进行按位与运算,就得到相应的坐标索引
插入新数据时如何计算其在数组的索引?
因为当数组长度小的时候,假设是16的话,n-1的二进制表示为1111,在进行按位与的时候,这样的值实际上只用了hash值的后四位,但是有的数组长度很大的时候,低位变化小,高位变化大,就很容易发生hash碰撞,所以这里把高低位都利用起来,从而解决这个问题。
为什么计算数组索引的时候要将哈希值与哈希值无符号右移16位进行异或运算?
hashmap
底层数组+链表实现,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashMap做了相关优化
初始size为11,扩容:newsize = olesize*2+1
HashTable
与hashMap相比的话,Treemap是可以比较大小的,会对key进行大小排序,其中可以用元素的自然排序,也可以使用集合中自定义的比较器来排序
在使用自然排序的时候,分为两种情况:1.jdk定义的对象2.自定义定义的对象
不同于hashmap的哈希映射,它的结构是红黑树,是一种二叉树
各自接口的特点
继承了AbstractMap,实现了Map,clonable,NavigableMap,Serializable接口
1.不允许存在重复的键
2.可以插入null键,null值;
3.可以对元素进行排序
4.无序集合(插入和遍历的顺序不同)
特点
TreeMap
HashMap和ConcurrentHashMap的区别
如果有多个线程对ConcurrentHashMap同一个key的value进行操作会不会出现问题
与hashMap非常相似,数组中和链表中的value值都是volatile 修饰,保证了获取时的可见性
HashEntry的组成
原理上来说:ConcurrentHashMap 采用了分段锁技术,其中 Segment 继承于 ReentrantLock。不会像 HashTable 那样不管是 put 还是 get 操作都需要做同步处理,理论上 ConcurrentHashMap 支持 CurrencyLevel (Segment 数组数量)的线程并发。每当一个线程占用锁访问一个 Segment 时,不会影响到其他的 Segment。
核心成员变量
1.将当前 Segment 中的 table 通过 key 的 hashcode 定位到 HashEntry。2.遍历该 HashEntry,如果不为空则判断传入的 key 和当前遍历的 key 是否相等,相等则覆盖旧的 value。3.不为空则需要新建一个 HashEntry 并加入到 Segment 中,同时会先判断是否需要扩容。4.最后会解除在 1 中所获取当前 Segment 的锁。
put方法
只需要将 Key 通过 Hash 之后定位到具体的 Segment ,再通过一次 Hash 定位到具体的元素上。由于 HashEntry 中的 value 属性是用 volatile 关键词修饰的,保证了内存可见性,所以每次获取时都是最新值。ConcurrentHashMap 的 get 方法是非常高效的,因为整个过程都不需要加锁
get方法
java1.7
将 1.7 中存放数据的 HashEntry 改为 Node,但作用都是相同的
其中抛弃了原有的 Segment 分段锁,而采用了 CAS + synchronized 来保证并发安全性
根据计算出来的 hashcode 寻址,如果就在桶上那么直接返回值。如果是红黑树那就按照树的方式获取值。就不满足那就按照链表的方式遍历获取值。
与java1.7的区别
java1.8
底层也是数组+链表
1.8 在 1.7 的数据结构上做了大的改动,采用红黑树之后可以保证查询效率(O(logn)),甚至取消了 ReentrantLock 改为了 synchronized,这样可以看出在新版的 JDK 中对 synchronized 优化是很到位的
底层
ConcurrentHashMap
Map集合
双列
ArrayList 底层是基于数组来实现容量大小动态变化的。
无惨构造函数方法的时候会默认建立一个长度为10的数组
扩容机制->首先是扩大原来容量的1.5倍,如果1.5倍还不够的话,则将容量赋为newCapacity;ArrayList 的最大存储能力:Integer.MAX_VALUE如果1.5倍太大的话,则用newCapacity = (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE 来扩容扩容是通过拷贝数组来实现的,所以尽量不扩容容量size 为集合中存储的元素的个数。elementData.length 为数组长度,表示最多可以存储多少个元素。 如果需要边遍历边 remove ,必须使用 iterator。且 remove 之前必须先 next,next 之后只能用一次 remove
ArrayList
底层是基于链表实现的
LinkedList
1.ArrayList底层是基于数组来实现的。
2.linked底层是基于链表来实现的。
3.如果是随机查找,且容量的大小是确定的话,用Arraylist速度更快
4.如果添加、删除,修改比较多的话,用LinkedList速度更快。
5.Linkedlist比arraylist多实现了Deque接口,所以linkedlist还可以来当做队列来使用。
Arraylist和LinkedList的区别
继承自Iterator,可以直接使用Iterator的迭代方法haxNext和next,ListIterator允许向后向前两个方向遍历
特有的列表迭代器
List 可重复
set 不可重复
Collection
单列
集合
8种数据类型
重载和重写的区别
链表的上一级结构是什么?java8中HashMap有什么变化?
链表
JDK:Java开发工具包,提供了Java的开发环境和运行环境。JRE:java运行环境,为Java的运行提供了所需环境。
JDK和JRE 的区别
Error:代表 JVM 自身的异常,无法通过程序来修正,最可靠的方式就是尽可能快地停止 JVM 的运行。Exception:代表程序运行中发生了意料之外的事情,这些意外的事情可以被Java异常处理机制处理。
Error和Exception有什么区别
空指针异常、字符串转换为数字异常、数组下标越界异常、方法传递参数异常、数据类型转换异常
常见的异常
处理异常主要有两种方式:一种try catch,一种是throws。
异常的处理方式,有什么区别?
异常
为什么要转换成红黑树,为什么不能是其他树(链表转红黑树,红黑树相对平衡,调整效率快)
数组
ThreadLocal?应用场景?
继承Thread类实现 Runnable 接口实现 Callable 接口
实现方式:
Runnable 接口:调用 run() 方法,没有返回值,不需要抛出异常Callable 接口:调用 call() 方法,有返回值,返回值类型是泛型,需要抛出异常
实现 Runnable 接口 和 实现 Callable 接口 有什么区别?
接口
偏向锁
轻量级锁
重量级锁
每次拿数据的时候都认为会存在竞争问题,所以每次都要加锁,一个一个来
悲观锁
简单解释:在表的设计中多了一个字段-->版本号字段,在a事务在读取数据库进行更新操作的时候,会把之前的版本号(假如是1),改为2或者其他的数字这个时候b事务读取的时候,会继续读取这条数据,他也会改变这个版本号,之前的版本号是1与a事务改变的版本号不一致这个时候,b事务会回滚当前的操作,来保证数据的安全性和完整性。
每次拿数据都不会认为存在竞争,所以不会加锁但是会比较拿到的值和期望值是否一致,以及通过版本号来判断数据是否被改变
乐观锁
锁的分类
间隙锁是什么,具体什么时候会加锁(具体什么时候加锁,这里要把所有情况都说清楚。。
ConcurrentHashMap的实现?1.7和1.8都说一下。(分段锁,synchronized,CAS)
可重入锁是什么,非可重入锁又是什么
SQLite如何加锁
Java里的锁,有哪几种(synchronized和Reentrantlock)
ReentrantLock有哪些特性(可重入,公平锁),可重入是如何实现的(有一个引用数,非可重入只有01值)
ReentrantLock有哪些实现类,它是一个接口
当某个线程获取ReentrantLock失败时,是否会从内核态切换回用户态?ReentrantLock如何存储阻塞的线程的?所以什么是自旋锁?
synchronized和Lock有什么区别,Lock的实现原理是什么(AQS,使用CLH锁,维护一个双向队列,存储阻塞线程。每个线程一直监听前一个节点的状态,如果调用了unlock,则停止自旋。
synchronized和CAS有什么区别,synchronized的实现原理是什么,CAS呢,CAS如何解决ABA问题(有锁,无锁。monitor(Owner字段,EntryQ字段(互斥锁)),判断有无改变,版本号)
谈一下AQS类,AQS全称,介绍实现原理
分布式锁了解吗
synchronized的锁升级
加锁有什么机制?
锁
RejectionHandler有哪些,具体如何操作
线程池的线程在执行完任务会立刻回收吗?(保留corePoolSize个核心线程)
容量为1的单一线程池容量固定的线程池容量不固定的线程池自定义线程池
自定义线程池的7大参数、4大拒绝策略
线程池的工作流程
线程池的原理
线程池有哪些
线程池
子主题
如果要线程安全,应该用什么类(ConcurrentHashMap)
Java如何实现线程安全(synchronized,ReentrantLock,AtomicInteger,ThreadLocal,CAS)
CAS如何解决ABA问题(版本号)
ThreadPoolExecutorle类的使用及其实现类有哪些
将数据设置为仅读。加锁:sychronized锁或者lock锁。
如果存在线程安全的话,怎么解决线程安全这个问题呢?
线程之间如何通信?怎么保证可见性?
线程安全
多线程
基础
TCP三次握手的过程,重发报文的过程。
TCP和UDP的区别
计算机网络五层协议
tcp怎么保持可靠性
拥塞控制具体怎么实现的
TCP三次握手和四次挥手
是域名系统,就是把电脑IP起一个别名-->域名 在访问域名的时候,会转化为相应的IP地址
DNS系统
网络
javaSE
过滤器的生命周期
1.post是给服务器提交数据,get是从服务器获取数据(也可以提交数据)2.post不能用书签收藏,get可以3.post传输数据的大小没有限制,get在URL上传递,最大大小是2048字节4.post相对安全,get不安全5.post不可以刷新,刷新的时候会重新提交,get可以刷新。6.post请求不能保存到cookie,get请求可以
post和get的区别
http协议有状态吗?
http协议已经发展到几了
http协议
Session存放在哪
Session
1.cookie是一小段存储在浏览器端的文本数据,大小不超过4k;2.有一个名称和一个值(可能还有其他的可选属性组成->eg:有效期,安全性,使用范围等);3.网站采取session机制的话,识别用户身份,通常会把sessionID存储在cookie中4.在网站上发送请求的时候,cookie会在请求头里一起发送给服务器端
cookie
javaWeb
MySQL的事务特性,事务隔离级别,分别解决了什么问题
事务的四个特性是怎么实现
事务
唯一索引和非唯一索引的区别
有什么用到索引
索引有哪些类型
什么是聚簇索引,什么是非聚簇索引
如果已经用到了索引,但因为数据量太大,比如几个亿,如何解决?(分治。追问:细说?加redis缓存,分库分表)
索引的概念
索引的作用
索引
mysql存储引擎的区别
MySQL有哪些事务隔离级别,分别解决了什么问题
隔离级别
MySQL的分库分表
遇到慢查询,如何解决?(explain,索引,覆盖索引,limit等)
mysql 的优化
join:取两个表的公共部分left join:以左边的表为主,右边表对应的数据如果不存在,则填nullright join:以右边的表为主,左边的表对应的数据如果不存在,则填null
join 、left join 、right join 有什么区别?
MySQL可以存储多少行
SQL如何解析
了解脏读吗
sql慢查询优化常见的步骤
为什么MyISAM查询性能好?
MySQL
数据库连接池怎么实现的
数据库水平切分,垂直切分的设计思路和切分顺序?
数据库
为什么要用Spring
AOP是什么,IOC是什么
默认是哪一种代理,两个代理的区别(反射,获取配置的类和属性,然后在运行时注入依赖。代理,JDK,CGLIB)
bean的生命周期
Spring如何解决循环依赖的
@Component:pojo包,创建 bean 对象@Repository:dao包@Service:service包@Controller:controller包@Bean:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
用于注册 Bean 对象的注解
@Scope:指定bean的作用范围。单例、多例等等
改变 Bean 作用范围的注解:
@Autowired:默认按照类型来装配(byType)@Resource:默认按照名称来装配(byName)@Qualifier:在自动按照类型注入的基础之上,再按照 Bean 的 id 注入。它在给字段注入时不能独立使用,必须和 @Autowire一起使用;但是给方法参数注入时,可以独立使用。@Value:通过@Value可以将外部的值动态注入到Bean中,可以为基本类型数据和String类型数据的变量注入数据
用于依赖注入的注解
@PostConstruct:指定初始化方法@PreDestroy:指定销毁方法
生命周期相关的注解
@AutoWired 和 @Resource 有什么区别
@AutoWired的实现原理bean的默认作用范围是什么?其他的作用范围?
1.如果同时指定name和type属性,则找到唯一匹配的bean装配,未找到则抛异常;2.如果指定name属性,则按照名称(byName)装配,未找到则抛异常;3.如果指定type属性,则按照类型(byType)装配,未找到或者找到多个则抛异常;4.既未指定name属性,又未指定type属性,则按照名称(byName)装配;如果未找到,则按照类型(byType)装配。
@Resource 的装配顺序:
注解
spring
和springboot的区别
springmvc
SpringBoot相比Spring的优势
springboot
soa和微服务的区别?
Spring Cloud
linux常用命令
怎么在linux中打开一个1G的文件
虚拟机
Redis有哪些数据类型以及使用场景?
zset结构,跳表
Redis的持久化如何做到的?(RDB+AOF)
点赞量怎么用Redis实现
RDB具体是如何实现的,RDB生成快照的时候,Redis会阻塞掉吗?(使用BgSave,fork一个子进程去并行生成快照,不会阻塞)
既然生成快照的中途依然可以执行Redis,那么从节点获取到快照是不完整的,如何同步?
怎么保持缓存一致性
redis线程模型
redis触发器
Redis如何删除过期键(定期+惰性)
Redis如何持久化(RDB+AOF)
怎么保证redist挂掉之后再重启数据可以进行恢复?
缓存雪崩和缓存穿透问题的解决方案?
如何保证缓存与数据库双写时数据一致性?
Redis分片有了解过吗?
Redis高可用,那主从同步,如何更换主节点
Redis如何解决key冲突的?
为什么要用redis/为啥要用缓存?
为啥用redis而不用map/guava做缓存?
redis和memcached的区别?
redis分布式锁的缺点
redis内存淘汰机制
Mysql里有2000w数据,reids只存了20w的数据,如何保证redis中的数据都是热点数据?
redis
设计一个秒杀系统?
设计模式
分支主题
Java 中的异常类均以 Throwable 类为父类,而 Throwable 又派生出 Error类 和 Exception类 这两大子类。Exception 类及其子类又可以划分为两大类:运行时异常、非运行时异常。
小帅取经
收藏
0 条评论
回复 删除
下一页