深度学习部分

过拟合与欠拟合

  1. 欠拟合指模型不能在训练集上获得足够低的训练误差;
  2. 过拟合指模型的训练误差与测试误差(泛化误差)之间差距过大;

反映在评价指标上,就是模型在训练集上表现良好,但是在测试集和新数据上表现一般(泛化能力差);

 

降低过拟合风险的方法

所有为了减少测试误差的策略统称为正则化方法,这些方法可能会以增大训练误差为代价。

  1. 数据增强
    1. 图像:平移、旋转、缩放
    2. 利用生成对抗网络(GAN)生成新数据
    3. NLP:利用机器翻译生成新数据
  2. 降低模型复杂度
    1. 神经网络:减少网络层、神经元个数
    2. 决策树:降低树的深度、剪枝
  1. 权值约束(添加正则化项)
    1. L1 正则化
    2. L2 正则化
  2. 集成学习
  1. 神经网络:Dropout
  2. 决策树:随机森林、GBDT
  1. 提前终止

 

降低欠拟合风险的方法

  1. 加入新的特征
  1. 交叉特征、多项式特征、...
  2. 深度学习:因子分解机、Deep-Crossing、自编码器
  1. 增加模型复杂度
  1. 线性模型:添加高次项
  2. 神经网络:增加网络层数、神经元个数
  1. 减小正则化项的系数
  1. 添加正则化项是为了限制模型的学习能力,减小正则化项的系数则可以放宽这个限制
  2. 模型通常更倾向于更大的权重,更大的权重可以使模型更好的拟合数据

 

反向传播算法

反向传播的作用/目的/本质

  1. 反向传播概述:

梯度下降法中需要利用损失函数对所有参数的梯度来寻找局部最小值点;

而反向传播算法就是用于计算该梯度的具体方法,其本质是利用链式法则对每个参数求偏导。

反向传播的公式推导

  1. 可以用 4 个公式总结反向传播的过程(反向传播的四个基本公式):

标量形式:

激活函数

激活函数的作用——为什么要使用非线性激活函数?

  1. 使用激活函数的目的是为了向网络中加入非线性因素;加强网络的表示能力,解决线性模型无法解决的问题

为什么加入非线性因素能够加强网络的表示能力?——神经网络的万能近似定理

  1. 神经网络的万能近似定理认为主要神经网络具有至少一个非线性隐藏层,那么只要给予网络足够数量的隐藏单元,它就可以以任意的精度来近似任何从一个有限维空间到另一个有限维空间的函数。
  2. 如果不使用非线性激活函数,那么每一层输出都是上层输入的线性组合;此时无论网络有多少层,其整体也将是线性的,这会导致失去万能近似的性质。
  3. 但仅部分层是纯线性是可以接受的,这有助于减少网络中的参数。

常见的激活函数

整流线性单元ReLU

  1. ReLU通常是激活函数较好的默认选择

ReLU 相比 sigmoid 的优势 (3)

  1. 避免梯度消失
  1. sigmoid函数在输入取绝对值非常大的正值或负值时会出现饱和现象——在图像上表现为变得很平,此时函数会对输入的微小变化不敏感——从而造成梯度消失;
  2. ReLU 的导数始终是一个常数——负半区为 0,正半区为 1——所以不会发生梯度消失现象
  1. 减缓过拟合
  1. ReLU 在负半区的输出为 0。一旦神经元的激活值进入负半区,那么该激活值就不会产生梯度/不会被训练,造成了网络的稀疏性——稀疏激活。
  2. 这有助于减少参数的相互依赖,缓解过拟合问题的发生。
  1. 加速计算
  1. ReLU 的求导不涉及浮点运算,所以速度更快。

为什么 ReLU 不是全程可微/可导也能用于基于梯度的学习?

  1. 虽然从数学的角度看 ReLU 在 0 点不可导,因为它的左导数和右导数不相等;
  2. 但是在实现时通常会返回左导数或右导数的其中一个,而不是报告一个导数不存在的错误。从而避免了这个问题。

Tanh定义域是负无穷到正无穷,值域是[-1,1]

 

正则化

Batch Normalization(批标准化)

  1. BN 是一种正则化方法(减少泛化误差),主要作用有:
  1. 加速网络的训练(缓解梯度消失,支持更大的学习率)。
  2. 防止过拟合。
  3. 降低了参数初始化的要求。

动机

  1. 训练的本质是学习数据分布。如果训练数据与测试数据的分布不同会降低模型的泛化能力。因此,应该在开始训练前对所有输入数据做归一化处理。
  2. 而在神经网络中,因为每个隐层的参数不同,会使下一层的输入发生变化,从而导致每一批数据的分布也发生改变;致使网络在每次迭代中都需要拟合不同的数据分布,增大了网络的训练难度与过拟合的风险。

L1/L2 范数的作用、异同

相同点

  1. 限制模型的学习能力——通过限制参数的规模,使模型偏好于权值较小的目标函数,防止过拟合。

不同点

  1. L1 正则化可以产生更稀疏的权值矩阵,可以用于特征选择,同时一定程度上防止过拟合;L2 正则化主要用于防止模型过拟合。
  2. L1 正则化适用于特征之间有关联的情况;L2 正则化适用于特征之间没有关联的情况。

 

为什么 L1 和 L2 正则化可以防止过拟合?

  1. L1 & L2 正则化会使模型偏好于更小的权值。
  2. 更小的权值意味着更低的模型复杂度;添加 L1 & L2 正则化相当于为模型添加了某种先验,限制了参数的分布,从而降低了模型的复杂度。
  3. 模型的复杂度降低,意味着模型对于噪声与异常点的抗干扰性的能力增强,从而提高模型的泛化能力。——直观来说,就是对训练数据的拟合刚刚好,不会过分拟合训练数据(比如异常点,噪声)——奥卡姆剃刀原理

 

 

方向导数与梯度以及它们之间的关系?

方向导数是一个值而梯度是一个向量。

梯度:是一个矢量,其方向上的方向导数最大,其大小正好是此最大方向导数。

(方向导数是函数在各个方向的斜率,而梯度是斜率最大的那个方向,梯度的值是方向导数最大的值。)

 

k-means算法https://www.cnblogs.com/qingyunzong/p/9760913.html

无监督学习中的聚类算法,K-Means是聚类算法中的最常用的一种,算法最大的特点是简单,好理解,运算速度快,但是只能应用于连续型的数据,并且一定要在聚类前需要手工指定要分成几类。

K-Means 聚类算法的大致意思就是“物以类聚,人以群分”:

1、首先输入 k 的值,即我们指定希望通过聚类得到 k 个分组;

2、从数据集中随机选取 k 个数据点作为初始大佬(质心);

3、对集合中每一个小弟,计算与每一个大佬的距离,离哪个大佬距离近,就跟定哪个大佬。

4、这时每一个大佬手下都聚集了一票小弟,这时候召开选举大会,每一群选出新的大佬(即通过算法选出新的质心)。

5、如果新大佬和老大佬之间的距离小于某一个设置的阈值(表示重新计算的质心的位置变化不大,趋于稳定,或者说收敛),可以认为我们进行的聚类已经达到期望的结果,算法终止。

6、如果新大佬和老大佬距离变化很大,需要迭代3~5步骤。

 

高斯滤波的公式 https://www.jianshu.com/p/73e6ccbd8f3f

高斯滤波在图像处理概念下,将图像频域处理和时域处理相联系,作为低通滤波器使用,可以将低频能量(比如噪声)滤去,起到图像平滑作用。

 

Dropout

Dropout一般用在全连接层中,卷积层中用的比较少,在卷积层中的作用也是随机把一些神经元屏蔽掉。

 

PCA

主成份分析,PCA算法有两种实现方法:基于特征值分解协方差矩阵、基于奇异值分解协方差矩阵。

 

 

过拟合和欠拟合

过拟合(over-fitting)是所建的机器学习模型或者是深度学习模型在训练样本中表现得过于优越,导致在验证数据集以及测试数据集中表现不佳。

 

 

正则化

回想下我们的模型,假如我们采用梯度下降算法将模型中的损失函数不断减少,那么最终我们会在一定范围内求出最优解,最后损失函数不断趋近0。那么我们可以在所定义的损失函数后面加入一项永不为0的部分,那么最后经过不断优化损失函数还是会存在。其实这就是所谓的“正则化”。

 

 

欠拟合怎么解决

这个情况往往出现在网络刚开始训练的时候,经过不断的训练,网络的欠拟合可能就会不怎么发生了。如果还是存在的话,可以尝试提高模型的复杂程度和增加一些特征点。

 

 

Batch Normalization

加速网络的训练。

好处:①不仅仅极大提升了训练速度,收敛过程大大加快;②还能增加分类效果,一种解释是这是类似于Dropout的一种防止过拟合的正则化表达方式,所以不用Dropout也能达到相当的效果;③另外调参过程也简单多了,对于初始化要求没那么高,而且可以使用大的学习率等。

(因为如果我们今天把每一个layer的feature都做Normalization,我们把每一个layer的feature的output都做Normalization,让他们永远都是比如说,对下一个layer来看,前个layer的statistics就会是固定的,他的training可能就会更容易一点。)

 

 

机器学习能完成,是假设训练数据和测试数据属于什么分布的?

独立同分布

 

 

常见的Loss函数

1、二分类任务,二值交叉熵(Binary Cross Entropy)

公式如下,其中y是真实值, 是预测值:

2、多分类任务,交叉熵(Cross Entropy)

公式如下,其中y是真实值, 是预测值:

3、回归任务计算均方误差 Mean Squared Error (squared L2 Norm)。

公式如下,其中y是真实值, 是预测值:

https://private.codecogs.com/gif.latex?loss%20%3D%20%5Cfrac%7B1%7D%7Bn%7D%20%5Csum_%7Bi%3D1%7D%5E%7Bn%7D%20%7B%28y-%5Chat%7By%7D%29%5E2%7D

4、二分类任务中,Focal loss主要是为了解决one-stage目标检测中正负样本比例严重失衡的问题。该损失函数降低了大量简单负样本在训练中所占的权重,也可理解为一种困难样本挖掘。

(聚焦于难训练的样本,对于简单的,易于分类的样本,给予的loss权重越低越好,对于较为难训练的样本,loss权重越好越好。简单有效)

 

 

深度学习中常用的Backbone

Alexnet:在Dropout和ReLU之后出现。

Vgg16/19:采用了更小的卷积核。

GoogLeNet:开始出现带分支的网络,不再是一个网络从头到尾。

ResNet:何凯明团队提出,把错误率降到了比人类还低的水平,网络的层数能达到1202层,具有里程碑的意义。

还有轻量化的网络:SqueezeNet和MobileNet

网络无限深,首先是计算资源的问题,最大的问题是容易出现梯度消失。

 

 

【神经网络】卷积层输出大小计算(长、宽、深度)

已知:输入图片大小 W×W,Filter大小 F×F,步长 S,padding的像素数 P

采用“valid”时输出的大小为:N = (W−F)/S+1。

采用“same”时输出的大小为:N=(W-F+2P)/S+1.

 

RNN,LSTM,GRU的异同https://www.cnblogs.com/AntonioSu/p/8798960.html

RNN的结构是由一个输入层、隐藏层、输出层组成:

https://img2018.cnblogs.com/i-beta/1108410/202002/1108410-20200217130354405-1702843706.png

LSTM由忘记门、输入门、输出门组成,是RNN的变体,在处理时序序列时,对长序列的处理能力更好。

GRU是LSTM的一个变体,可以说是一个升级版,比LSTM更加简洁一些,可以看成是将LSTM的输入门和忘记门合成了一个单一的更新门。

(使用LSTM的原因之一是解决RNN Deep Network的Gradient错误累积太多,以至于Gradient归零或者成为无穷大,所以无法继续进行优化的问题。GRU的构造更简单:比LSTM少一个gate,这样就少几个矩阵乘法。在训练数据很大的情况下GRU能节省很多时间。)

 

 

能在移动端运行的深度学习模型https://blog.csdn.net/zeusee/article/details/89601634

目前,很多公司都推出了开源的移动端深度学习框架,基本不支持训练,只支持前向推理。

Caffe2、TensorFlow Lite、等。

 

 

常见的滤波器

傅里叶序列和SIFT

 

 

 

 

 

 

 

 

 

机器学习部分

SGD,Momentum,Adagard,Adam原理

SGD:随机梯度下降,与数据集的batch有关。

Momentum:动量学习,解决梯度下降不稳定、容易进入鞍点的缺点。

Adagard:Adagrad将之前梯度的平方求和再开根号作为分母,会使得一开始学习率呈放大趋势,随着训练的进行学习率会逐渐减小。

Adam:集众家之所长,结合momentum和adagrad两种算法的优势。

 

L1不可导的时候该怎么办

当目标函数不可导时,loss不会再下降。使用的方法为坐标轴下降法,对于有m个特征的目标函数,可以先固定m-1个特征,只对其中一个特征求局部最优解,避免不可导的问题

 

sigmoid函数特性

定义域为https://uploadfiles.nowcoder.com/images/20190315/311436_1552619092213_171B20A604B88BE2CC570EF936359F57

值域为(0,1)

函数在定义域内为连续和光滑的函数

处处可导,导数为https://uploadfiles.nowcoder.com/images/20190315/311436_1552619110289_2FC0EF550E43398C033CAF8AE5CD23F6

 

一个活动,n个女生手里拿着长短不一的玫瑰花,无序的排成一排,一个男生从头走到尾,试图拿更长的玫瑰花,一旦拿了一朵就不能再拿其他的,错过了就不能回头,问最好的策略?

37%法则:先观察r-1个女生,然后在后面n-r+1个女生中选比前面都长的玫瑰花,这样选得最长玫瑰花的概率为0.368。

 

某大公司有这么一个规定:只要有一个员工过生日,当天所有员工全部放假一天。但在其余时候,所有员工都没有假期,必须正常上班。这个公司需要雇用多少员工,才能让公司一年内所有员工的总工作时间期望值最大?

总工作时间期望:E=n*(1-1/365)∧n

取对数:ln E=n*ln(364/365)+ln n

对n求偏导:d ln E/ d n = ln(364/365)+1/n

令偏导为0,可得:n=354,365

 

切比雪夫不等式

切比雪夫不等式,描述了这样一个事实,事件大多会集中在平均值附近。

https://uploadfiles.nowcoder.com/images/20190315/311436_1552619824709_122D0CDD1D8EE589AA0696D772362505

https://uploadfiles.nowcoder.com/images/20190401/1536691_1554124538112_551319652C0DB9A582EB9335833EA96C

 

一根绳子,随机截成3段,可以组成一个三角形的概率有多大

设两条边分别为x,y,需要满足x<0.5,y<0.5,x+y>0.5,才能构成三角形。画图算面积,蓝色部分为所有可能取值范围,黄色部分为所有有效取值范围。因此,结果为0.25。

https://uploadfiles.nowcoder.com/images/20200412/844869655_1586680432525_B6C31D01D41C9E1714958F9C56D01D8F

 

最大似然估计和最大后验概率的区别?

最大似然估计(MLE)和最大后验概率(MAP)。

相同点: 都是为了找到参数的某一个取值,这个取值使得得到目前观察结果的概率最大。(通过比较该参数不同取值下观察结果的条件概率)

不同点:MAP 考虑了模型的先验分布, 而MLE 假设模型是均匀分布。 可以说,MLE是MAP的一种特例。

 

 

什么是共轭先验分布

假设https://uploadfiles.nowcoder.com/images/20190315/311436_1552620116270_1C442D3875E749F08F3A423E76A4F05C 为总体分布中的参数,https://uploadfiles.nowcoder.com/images/20190315/311436_1552620076109_BF16EA28BE27AB41BEEF50E93A0A40CA 的先验密度函数为https://uploadfiles.nowcoder.com/images/20190315/311436_1552620136750_F6C5D0F1930B964FFEA89DDF696882A1 ,而抽样信息算得的后验密度函数与https://uploadfiles.nowcoder.com/images/20190315/311436_1552620177179_1E85417CAFB6E126FC164557E874F041 具有相同的函数形式,则称https://uploadfiles.nowcoder.com/images/20190315/311436_1552620200305_FE5C121DE1782542C49C90C992320882https://uploadfiles.nowcoder.com/images/20190315/311436_1552620224564_CB64FF4F9ABB3A6860F6198E1DF33320 的共轭先验分布。

(当假设参数的后验分布和先验分布属于同一种类型的分布时称为共轭先验分布,例如参数θ的先验分布和后验分布均为高斯分布)

 

逻辑回归https://zhuanlan.zhihu.com/p/28408516

逻辑与线性回归有很多相同之处,去除Sigmoid映射函数的话,逻辑回归算法就是一个线性回归。可以说,逻辑回归是以线性回归为理论支持的,但是逻辑回归通过Sigmoid函数引入了非线性因素,因此可以轻松处理0/1分类问题。

 

 

 

 

 

 

 

 

 

 

 

 

 

数据结构部分

B树和B+的树的区别和联系

B树又叫B-树,查找过程中可能在中间结点就结束了,不一定到达叶子结点。

B+树一定会查找到叶子结点,左子树的数都比关键字小,右子树上的数都大于等于关键字。B+树叶子结点连在一起是一个有序的链表。

 

红黑树的结构及应用

红黑树是一种含有红黑结点并能自平衡的二叉查找树。它必须满足下面性质:

性质1:每个节点要么是黑色,要么是红色。

性质2:根节点是黑色。

性质3:每个叶子节点(NIL)是黑色。

性质4:每个红色结点的两个子结点一定都是黑色。

性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。

当在10亿数据进行不到30次比较就能查找到目标时,不禁感叹编程之魅力!人类之伟大呀! —— 学红黑树有感。

红黑树在JDK源代码中的应用最典型的就是TreeMap,以及Java 8中的TreeSet。

 

 

哈希表解决冲突的两种方式

1、开放定址法  (a)线性探测(b)线性探测再散列

2、拉链法

拉链法的优点:

1)处理冲突简单。2)适合造表前无法确定表长的情况。3)拉链法的装填因子可以大于或等于1。4)拉链表构造的散列表,删除操作容易实现。只用简单删除上面的结点即可,而开放定址法不能简单的删除,否则容易截断在它之后填入散列表的同义词的结点的查找路径,开放定址法的删除操作实际上只是做了一个简单的标记,而不能真正删除结点。

拉链法的缺点:

指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间,而若将节省的指针空间用来扩大散列表的规模,可使装填因子变小,这又减少了开放定址法中的冲突,从而提高平均查找速度。

 

 

跳表:

跳表的原理非常简单,跳表其实就是一种可以进行二分查找的有序链表。

 

 

Java部分

synchronized 关键字的实现原理:

synchronized给出的答案是在软件层面依赖于JVM虚拟机。

 

进程和线程之间的联系和区别:

进程是资源分配和管理的基本单位。线程是更小的独立运行的基本单位,线程也被称为轻量级的进程。一个程序至少包含一个进程,一个进程至少包含一个线程。

线程的执行开销小,但是不利于资源的保护和管理。进程资源开销大,但是适合资源的保护和管理。

Tomcat内部采用的是多线程,上百个客户端同时访问一个Web应用。

多线的实现方式:1、继承Thread类;2、实现Runnable(Callable接口)

 

并发和并行

并发是指宏观上一段时间内能同时运行多个程序,而并行是指同一个时刻能运行多个指令。

 

线程池的作用

多线程运行时间,系统不断的启动和关闭新线程,成本非常高,会过渡消耗系统资源,以及过渡切换线程的危险,从而可能导致系统资源的崩溃。这时,线程池就是最好的选择了。

 

多线程通信的方法

1.全局变量  2.Message消息机制  3.CEvent对象

 

时间局部性和空间局部性

在CPU访问寄存器时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,这就被称为局部性原理。 

时间局部性(temporal locality) :

时间局部性指的是:被引用过一次的存储器位置在未来会被多次引用(通常在循环中)。 

空间局部性(spatial locality) :

如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。

 

 

死锁:

在两个或多个并发进程中,如果每个进程持有某种资源而又都等待别的进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁,也就是多个进程无限期的阻塞、相互等待的一种状态。

“鸵鸟策略”来处理死锁问题。

 

 

活锁:

例子:马路中间有条小桥,只能容纳一辆车经过,桥两头开来两辆车A和B,A比较礼貌,示意B先过,B也比较礼貌,示意A先过,结果两人一直谦让谁也过不去。

 

 

产生死锁的原因?

  1. 互斥:一个资源每次只能被一个进程使用。
  2. 请求与保持:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
  3. 不剥夺:进程已获得的资源,在末使用完之前,不能强行剥夺。
  4. 循环等待:若干进程之间形成一种头尾相接的循环等待资源关系。

 

 

Collection集合常用实现类及方法

ArrayList 有序,底层数组实现,遍历轮询效率高

LinkedList 链表形式存储,增删效率高

HashSet 无序,不重复(通过equals()和hashCode方法过滤是否重复) 

TreeSet  无序,不重复(通过实现Comparable的CompareTo方法过滤重复元素)

 

 

 

ArrayList 和LinkedListed 的区别?

回答顺序存储(数组)和单链表的区别和优缺点即可。其中注意:LinkedListed可能是由双向链表的数据结构。

 

 

HashMap是否线程安全,线程不安全应该使用什么?ConcurentHashMap说一下

Hashmap仅可以单个线程访问,Hashtable可以多线程访问,但是会设置同步锁。ConcurentHashMap是Hashtable的替代品,使用了锁分段技术,对map进行分段加锁,这样就可以多线程访问。

 

Spring IOC:https://www.cnblogs.com/xdp-gacl/p/4249939.html

IoC(控制反转) 、DI(依赖注入),

IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

IoC和DI是同一个概念的不同角度描述,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。

控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。

 

Springboot和SpringMVC有什么区别和联系

spring boot只是一个配置工具,整合工具,辅助工具。

springmvc是框架,项目中实际运行的代码

最简练的语言概括就是:

Spring 是一个“引擎”;

Spring MVC 是基于Spring的一个 MVC 框架;

Spring Boot 是基于Spring4的条件注册的一套快速开发整合包。

 

Spring MVC请求流程:

SpringMVC框架是一个基于请求驱动的Web框架,并且使用了‘前端控制器’模型来进行设计,再根据‘请求映射规则’分发给相应的页面控制器进行处理。

 

SpringBoot的核心配置文件有哪些?区别

SpringBoot的核心配置文件有application和bootstrap配置文件。

用途:

application文件主要用于Springboot自动化配置文件。

bootstarp文件主要有以下几种用途:

使用Spring Cloud Config注册中心时,需要在bootstarp配置文件中添加链接到配置中心的配置属性来加载外部配置中心的配置信息。

一些固定的不能被覆盖的属性。

一些加密/解密的场景。

 

 

 

 

 

== 和equals区别

"=="是判断两个变量或实例是不是指向同一个内存空间。

"equals"是判断两个变量或实例所指向的内存空间的值是不是相同。

 

String、StringBuffer和StringBuilder的区别https://blog.csdn.net/csxypr/article/details/92378336

1、String类是不可变类,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。

2、StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。

3、StringBuilder

  StringBuilder类也代表可变字符串对象。实际上,StringBuilder和StringBuffer基本相似,两个类的构造器和方法也基本相同。不同的是:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。

 

接口(Interface)与抽象类(Abstract Class)的区别?

1、接口使用interface修饰;2、接口不能被实例化;3、一个类只能继承一个类,但是可以实现多个接口;4、接口中方法均为抽象方法;5、接口中不能包含实例域或静态方法(静态方法必须实现,接口中方法是抽象方法,不能实现)

 

 

 

 

 

Bean 的生命周期:

在传统的Java应用中,bean的生命周期很简单,使用Java关键字 new 进行Bean 的实例化,然后该Bean 就能够使用了。一旦bean不再被使用,则由Java自动进行垃圾回收。

Spring管理Bean的生命周期比较复杂:

1、Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化

2、Bean实例化后对将Bean的引入和值注入到Bean的属性中

3、如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法

4、如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入

5、如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。

6、如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。

7、如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用

8、如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。

9、此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。

10、如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。

 

 

Java 内存模型https://www.jianshu.com/p/15106e9c4bf3

java内存模型(Java Memory Model,JMM)是java虚拟机规范定义的,用来屏蔽掉java程序在各种不同的硬件和操作系统对内存的访问的差异,这样就可以实现java程序在各种不同的平台上都能达到内存访问的一致性。

 

Java常见的内存溢出异常及解决方法

Java的内存溢出,主要是两方面的异常:堆内存溢出、非堆内存溢出。通过设置解决方法:手动设置Heap size和MaxPermSize大小来解决问题。

建议:将相同的第三方jar文件移置到应用服务器的公用lib目录下,这样可以达到减少jar文件重复占用内存的目的。

 

有界队列

有界队列:就是有固定大小的队列。比如设定了固定大小的 LinkedBlockingQueue,又或者大小为 0,只是在生产者和消费者中做中转用的 SynchronousQueue。

无界队列:指的是没有设置固定大小的队列。这些队列的特点是可以直接入列,直到溢出。当然现实几乎不会有到这么大的容量(超过 Integer.MAX_VALUE),所以从使用者的体验上,就相当于 “无界”。比如没有设定固定大小的 LinkedBlockingQueue。

 

 

jvm的新生代、老年代、永久代关系https://blog.csdn.net/qq_19734597/article/details/80958817

1、Minor GC是发生在新生代中的垃圾收集,采用的复制算法;

2、新生代中每次使用的空间不超过90%,主要用来存放新生的对象;

3、Minor GC每次收集后Eden区和一块Survivor区都被清空;

4、老年代中使用Full GC,采用的标记-清除算法。

 

 

索引原理

索引的目的在于提高查询效率,与我们查阅图书所用的目录是一个道理:先定位到章,然后定位到该章下的一个小节,然后找到页数。

 

 

 

 

 

 

操作系统

操作系统中的堆和栈:

栈:

执行期间编译器自动分配,编译器用它实现函数调用,调用函数时,栈增长,函数返回时,栈收缩。局部变量、函数参数、返回数据、返回地址等放在栈中

栈的特点

1、内存分配取决于编译器,用户栈在程序运行期间可以动态的扩展和收缩。

2、和数据结构中的“栈”本质上是不一样的,但是操作方式类似于栈。

3、数据从栈中的进出满足“后进先出”的规律。

4、栈向低地址方向增长,esp(栈指针)指向栈顶元素。

堆:

动态储存器分配器维护着的一个进程的虚拟存储器区域。一般由程序员分配释放(堆在操作系统对进程初始化的时候分配),若程序员不释放,程序结束时可能由OS回收,每个进程,内核都维护着一个变量brk指向堆顶。

堆的特点:

1、内存分配取决于程序员,C/C++可以手动释放该片内存。

2、和数据结构的”堆“完全两回事,没有半点关系,在这里堆的结构更像链表。

3、所有的对象,包括数组的对象都存在堆上。

4、堆内存被所有的线程共享。

5、引用类型总是放在堆中。

6、堆向高地址方向增长,内核都维护的变量brk指向堆顶。

 

 

 

 

数据库部分

Redis常见数据类型

Redis支持的数据类型:字符串string、列表list、哈希hash、集合set。

 

Reids的持久化方式

Redis的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”);也可以把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”)。

(redis提供两种方式进行持久化,一种是RDB持久化(原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化),另外一种是AOF(append only file)持久化(原理是将Reids的操作日志以追加的方式写入文件)。)

 

Mysql数据库存储引擎

常见的三种引擎:InnoDB、MyISAM、MEMORY。

InnoDB 的优点是提供了良好的的事务处理、崩溃修复能力和并发控制。缺点是读写效率较差,占用的数据空间相对较大。

MyISAM的优点是效率高、占用空间小。缺点是不支持事务的完整性和并发性。采用B+树作为存储结构,具备较高的插入和查询速度。

Memory是将全部数据存储在内存中,速度快,安全性不高,与前面两个有完全的不同。

 

聚簇索引与非聚簇索引

聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据。

非聚簇索引(又叫做二级索引):将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因

 

数据库的底层数据结构是什么,磁盘的数据结构是什么?

关于数据库索引的数据结构,大多数数据库都是采用B树。

磁盘的数据结构包括:1):主引导扇区(MBR)2):操作系统引导扇区(OBR)3)文件分配表(FAT)4):目录区(DIR)5):数据区(DATA)

 

 

数据库左连接、右连接、内连接、全连接(外连接)

左连接是左边表的所有数据都有显示出来,右边的表数据只显示共同有的那部分,没有对应的部分只能补空显示,所谓的左边表其实就是指放在left join的左边的表。

右连接正好是和左连接相反的,这里的右边也是相对right join来说的,在这个右边的表就是右表。

内连接是一种一一映射关系,就是两张表都有的才能显示出来。

全连接查询出左表和右表所有数据,但是去除两表的重复数据。

 

 

数据库读写分离机制,如何做分库分表的?

读写分离是用来解决数据库的读性能瓶颈的。

数据库水平切分,也是一种常见的数据库架构,是一种通用算法,将数据库进行分割的架构。一个水平切分集群中的每个数据库,通常称为一个“分片”。每一个分片中的数据没有重合,所有分片中的数据并集组成全部数据。

 

 

 

C++

指针和引用的区别?

相同点:

1). 都是地址的概念;

2). 都是“指向”一块内存。指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名;

3). 引用在内部实现其实是借助指针来实现的,一些场合下引用可以替代指针,比如作为函数形参。

不同点:

1). 指针是一个实体,而引用(看起来,这点很重要)仅是个别名;

2). 引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;

3). 引用不能为空,指针可以为空;

4). “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;

5). 指针和引用的自增(++)运算意义不一样;

6). 引用是类型安全的,而指针不是 (引用比指针多了类型检查)

7). 引用具有更好的可读性和实用性。

 

 

引用占用内存空间吗?

如下代码中对引用取地址,其实是取的引用所对应的内存空间的地址。这个现象让人觉得引用好像并非一个实体。但是引用是占用内存空间的,而且其占用的内存和指针一样,因为引用的内部实现就是通过指针来完成的。

比如 Type& name; <===> Type* const name。

int main(void)

{

        int a = 8;

        const int &b = a;

        int *p = &a;

        *p = 0;

        cout<<a; //output 0

    return 0;

}

 

 

指针数组和数组指针的区别

数组指针,是指向数组的指针,而指针数组则是指该数组的元素均为指针。

 

 

解释下封装、继承和多态?

1). 封装:

封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称之为类)。

封装的意义在于保护或者防止代码(数据)被我们无意中破坏。

2). 继承:

继承主要实现重用代码,节省开发时间。

子类可以继承父类的一些东西。

a. 公有继承(public)

公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的,不能被这个派生类的子类所访问。

b. 私有继承(private)

私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。

c. 保护继承(protected)

保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的

3)多态https://www.runoob.com/cplusplus/cpp-polymorphism.html

多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。

C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。

 

 

什么时候生成默认构造函数(无参构造函数)?什么时候生成默认拷贝构造函数?什么是深拷贝?什么是浅拷贝?默认拷贝构造函数是哪种拷贝?什么时候用深拷贝?

1). 没有任何构造函数时,编译器会自动生成默认构造函数,也就是无参构造函数;当类没有拷贝构造函数时,会生成默认拷贝构造函数。

2). 深拷贝是指拷贝后对象的逻辑状态相同,而浅拷贝是指拷贝后对象的物理状态相同;默认拷贝构造函数属于浅拷贝。

3). 当系统中有成员指代了系统中的资源时,需要深拷贝。比如指向了动态内存空间,打开了外存中的文件或者使用了系统中的网络接口等。如果不进行深拷贝,比如动态内存空间,可能会出现多次被释放的问题。是否需要定义拷贝构造函数的原则是,是类是否有成员调用了系统资源,如果定义拷贝构造函数,一定是定义深拷贝,否则没有意义。

 

 

构造函数和析构函数的执行顺序?

构造函数

1). 首先调用父类的构造函数;

2). 调用成员变量的构造函数;

3). 调用类自身的构造函数。

析构函数

对于栈对象或者全局对象,调用顺序与构造函数的调用顺序刚好相反,也即后构造的先析构。对于堆对象,析构顺序与delete的顺序相关。

 

什么时候用static? static修饰的是静态全局变量,值是可以修改的。不能改变值的叫常量(const)。

需要一个数据对象为整个类而非某个对象服务,同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部,对外不可见。

 

 

C++中指针常量与常量指针的区别

指针常量就是指针本身是常量,换句话说,就是指针里面所存储的内容(内存地址)是常量,不能改变。但是,内存地址所对应的内容是可以通过指针改变的。

常量指针就是指向常量的指针,换句话说,就是指针指向的是常量,它指向的内容不能发生改变,不能通过指针来修改它指向的内容。但是,指针自身不是常量,它自身的值可以改变,从而指向另一个常量。

 

 

 

 

 

计算机网络

tcp为什么要三次握手,tcp为什么可靠?

为什么不能两次握手:(防止已失效的连接请求又传送到服务器端,因而产生错误)

TCP三次即建立TCP连接,指建立一个TCP连接时,需要客户端服务端总共发送3 个包以确认连接的建立。在socket编程中,这一过程中由客户端执行connect来触发,流程如下:

https://images2015.cnblogs.com/blog/364303/201608/364303-20160815220601750-1518158934.png

三次握手的通俗理解

 

 

 

四次挥手

所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发,整个流程如下图所示:

 

四次挥手的通俗理解

 

TCP/UDP 网络模型一共有几层

网络接口层、网络层、传输层、应用层。

 

OSI七层模型:

物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

 

 

 

TCP和UDP的区别和联系:

             TCP           UDP

是否连接     面向连接      面向非连接

传输可靠性   可靠          不可靠

应用场合     少量数据      传输大量数据

速度         慢             快

TCP与UDP区别总结:

1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接

2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付

3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的

UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

5、TCP首部开销20字节;UDP的首部开销小,只有8个字节

6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

 

 

 

 

 

 

 

 

 

 

 

 

 

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐