面试准备过程中,记录下来的一些点

面试准备过程中,记录下来的一些点

1.REST(representational state transfer) 接口开发 接口规范

幂等:无论操作多少次,请求的结果都是一样的。
安全:访问资源不会对资源发生修改。
POST的不幂等,应该被设计为用于提交修改。

接口 幂等 安全
POST × ×
GET
HEAD
DELETE ×
PUT ×

2. 数据分箱的相关概念以及练习

等宽分箱:可以参考百度回答
800、 1000、 1200 、1500、 1500、 1800、 2000、 2300、 2500、 2800、 3000、 3500、 4000、 4500、 4800、 5000按照宽度为800进行分箱。
就是分为等区间的箱。

  1. 800、1000、1200、1500、1500
  2. 1800、2000、2300、2500
  3. 2800、3000、3500
  4. 4000、4500、4800
  5. 5000

3. K近邻(KNN)

计算原理:
输入不带标签的数据, 将其每个特征与样本数据(带标签分类)对应的特征进行比较。计算新数据与样本每一条数据的距离,对求得的所有距离进行排序。距离小的说明相似。取TopK,K个数据中出现最多的分类标签作为新数据的分类。

4. 决策树

信息熵(香农熵):混乱程度
信息增益:划分数据集前后信息发生的变化。他等于前熵减去后熵,理解起来就是,添加一个特征之后,对于结果确定性的判断影响了多少。信息增益越大,说明该信息越有用,表现为该特征是关键特征。
例子:明天有可能下雨,如果知道了明天阴天,那么下雨的不确定性就会降低很多。
优点:计算复杂度不高,输出易理解。对中间的缺失值不敏感,可以处理不相关特征数据(就是说如果有一些特征对于结果的作用影响不大,那么他们也不会影响决策树的准确构建,同样的道理,我们也很容易知道哪些字段比较重要)。
缺点:难以预测连续的字段
类别较多时,错误增加的可能会比较快(过拟合)。

5. 朴素贝叶斯

贝叶斯分类器,二分类c1、c2。数据是数值型或者bool型。条件概率。新数据(x,y),比较P(c1|x,y)和P(c2|x,y)
朴素贝叶斯基于两个假设:特征独立,并且特征同等重要
就文档分类描述工作原理:
看不懂。。
算法特点:
优点:对少量数据也适用,可以处理多类别问题
缺点:输入数据需要满足数值型或者bool型,往往都需要进行数值转化。
用途案例:社区侮辱性言论屏蔽。

6. java控制权限,编译时控制,可以通过反射访问私有成员,私有方法

关键字 类内 包内 子孙 包外
public
protected ×
default × ×
private × × ×

7. 字符串的比较都是用equals比较,不用==

8. Integer和int的区别

null和0
一个是封装的类,一个是基本数据类型
前者可以表达书未赋值和赋值为0的区别。int不能表达出未赋值的意思。

9. 抽象类和普通类的区别:

不能创建类的实例,允许有抽象方法。

10. java深拷贝和浅拷贝

深拷贝实现cloneable接口,重写clone方法
实现彻底的深拷贝需要逐步重写clone方法

11. 内部类:

成员内部类 :类似于成员变量
方法内部类 :只能访问方法中定义的final类型的变量
匿名内部类 :实际上也是方法内部类的一种。特点是只能实例化一次,而且没有名字。需要继承一个基类,但是不使用extends关键字。或是实现一个接口,也不使用implements关键字。

12. this.getClass().getName();

super.getClass().getName();
//两句等效。

super.getClass().getName();
this.getClass().getSuperClass().getName();//这个才能获取到父类的名字。因为getClass()方法是Object基类的一个final方法。super.getClass()和this.getClass()访问的实际上都是Object的getClass()方法,是同一个。getClass()用于获取当前运行类的名字。获取父类需要用getSuperClass()

13. 关于try{return;}catch{}finally{return;} try中返回只是将值存在函数栈,继续执行finally中的return ,更新了值。之后返回控制权。

14. final finally finalize区别:

final关键字 用于修饰
finally总是执行 捕获异常时使用
finalize是Object的一个方法。是垃圾回收期调用,用来回收资源使用的。可以重写。

15. 创建线程的两种方式:

继承Thread类:

MyThread mthread=new MyThread();
mthread.start();

实现Runable接口

MyThread mthread=new MyThread();
new Thread(mthread).start();

16. servlet

继承HttpServlet
doGet(HttpServletRequest,HttpServletResponse)
生命周期

  1. init() 初始化
  2. service() 处理客户端请求。检查请求类型(put,get,post,delete)
  3. doXX 比如doGet,doPost..
  4. destory()

17. 软件开发模型

  1. 迭代模型

  2. 螺旋模型
    何时使用:大系统风险大,需求不明
    可以看做是每个阶段都事先加了风险分析的快速原型模型。一圈一圈螺旋线。

  3. 增量模型

  4. 快速原型模型
    何时使用:需求不明确时
    特点:可以跟客户进行全面的沟通,获取更为详细明确的需求和需求变化。原型开发简单,周期短,经济。
    过程见图:
    图片说明

  5. 瀑布模型
    何时使用:大系统风险小
    特点:经典,老套;前一阶段的输出作为下一阶段的输入,顺序性和依赖性;每个阶段都要交付合格的文档;如果用户需求突然变更会很头疼。
    过程: 可行性研究 ->需求分析->概要设计 ->详细设计 ->编码以及单元测试->测试

18. 冯诺依曼体系结构

存储器:存放数据和程序
控制器:控制指挥程序和数据的输入运行,处理运算结果
运算器:完成算数运算和逻辑运算,并暂存中间结果
输入:键盘,鼠标
输出:显示器
图片说明

链接-阿里2019实习内推,五轮技术面+一轮HR面,Java岗面经

19. 线程池,说一下线程池工作原理,任务拒接策略有哪几种

首先说一下线程池的意义:
执行一个任务的耗时,包含三个部分:T1创建线程,T2执行任务,T3销毁线程。如果T1+T3的时间远大于T2,那么创建并维护一个线程池来管理线程就很有必要了,对于提升服务性能有很大的帮助。重复利用闲置线程,尽量避免创建和销毁线程的耗时操作。
常见线程池的类型:
newSingleThreadExecutor池中单线程工作
newFixedThreadExecutor池中的线程数固定。池满,新任务则等待。
newCacheThreadExecutor重点在于,空闲线程超过固定时间之后,会被回收。当需要新的线程还会重新创建。
newScheduleThreadExecutor线程数无限。

java提供了一个java.util.concurrent.Executors工具类用于创建线程池。读其源码,可以看到它实际上是通过 ThreadPoolExecutor 在创建线程池。
看ThreadPoolExecutor的构造方法:

public ThreadPoolExecutor(int corePoolSize,//即使没有任务,依然存在的线程(等候任务的分配)。
                              int maximumPoolSize,//哪怕任务再多,也不能分配更多的线程(考虑机器性能有上限)
                              long keepAliveTime,//空转线程(非核心线程)最长空转时间,自动销毁。
                              TimeUnit unit,//指定存活时间的单位
                              BlockingQueue<Runnable> workQueue,//提交的任务都在队列中。阻塞队列。队列内的任务数存在上限。
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler//拒绝策略,当线程池满了,并且队列也是满的时候,会调用,拒绝执行该任务。
                              ) {
        if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

任务提交执行流程:

int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {//如果当前活跃线程数小于核心线程数,则可以直接创建线程执行任务(addworker())
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {//将任务添加到阻塞队列,并且添加成功
            int recheck = ctl.get();//再次检查
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))//添加到阻塞队列失败。执行拒绝策略
            reject(command);

总的来说:新任务到来,首先检查当前活跃线程数是否小于核心线程数,小于,则获取线程并执行任务,不小于,则再判断阻塞队列是否已满,不满,则添加任务入队列等待执行,满了,则判断线程池是否满了,如果未满,则创建线程执行任务,满了则拒绝任务执行。
拒绝策略的种类(内置四种):

  1. discardpolicy 直接抛弃,不执行任务
  2. DiscardOldestPolicy 抛出队列中最老的任务,并尝试重新运行刚提交的任务
  3. abortpolicy(默认) 不执行任务并抛出异常RejectedExecutionException。需要try catch。
  4. callerRunspolicy 线程池没有资源了,本来想让别人帮忙干活的,现在只能自己干了。会造成当前线程的阻塞。

20. 进程和线程的区别

我们写的代码,都可以称为是一个程序,一个程序的运行,至少需要一个进程,一个进程至少需要一个线程。
多个进程之间有独立的内存单元,互不干扰,而线程之间共享内存。所以就会有经常遇到的线程安全,同步等问题。
进程是系统进行资源分配和资源调度的一个独立单位。
线程是CPU进行调度和分配的单位。

21. 线程同步的方式有哪些?

22. 事务的四大特性ACID

A:原子性。事务中所有的操作要么成功,要么全部失败回滚到操作之前。
C:一致性。事务必须要使数据库从一个一致性状态转到另一个一致性状态。怎么理解这个一致性?比如说转账,两个人的总额是10000,不管怎么来回转,最终的操作结果必定满足总额还是10000.
I:isolation隔离性。事务的操作不会被外界操作或者别的事务操作所影响。特别是在遭遇并发的时候,事务的隔离级别参考下面。
D:持久性。事务一旦提交,作出的更改就是永久性的。

23. 事务的隔离级别

如果没有事务隔离性,会发生以下情况:
脏读:举个例子,A向B转账。A的所有操作都在一个事务中,事务中包含两个操作+100和-100。在+100之后,事务暂未提交,此时B那边查账会发现确实有100转进来,而当A提交事务之后,-100执行。B再查账会发现余额为0。所谓脏读,就是一个事务中读取了另一个未提交的事务的数据。
不可重复读:见下面一段话。
幻读:见下。
幻读和不可重复读都是读取了已经提交的事务数据。脏读读取的是未提交的事务数据。不可重复读针对的hi同一个数据项,两次读取的结果不一样。幻读是针对一批数据,事务A提交了修改,同时事务B也提交了修改,但是如果此时A再查询的话,会发现,“咦,我明明已经完成修改了,怎么还有不符合我修改之后的数据项啊?”实际上这是事务B在捣鬼。
Serializable串行化:隔离最高。同时避免三种错误。
Repeatable read可重复读:可以避免脏读和不可重复读。
Read committed读已提交(读取的数据是已经提交的):可以避免脏读。(常见的默认隔离级别)
Read unconmmited读未提交(会发生读取未提交的数据):隔离最低
请在事务开启之前,设置隔离级别

mysql>set transaction isolation level repeatable read;//设置隔离级别
mysql>select @@tx_isolation;//查询当前隔离级别

24.Hive的特点说一下

Hive是基于hdfs建立的数据仓库, 将数据文件存成一张表,称为元数据, 记录表的所属的数据库, 表的字段等信息。 具有类似sql的查询功能,面对较大的数据查询,其将sql自动转为MR的操作可以充分利用集群的计算资源进行查询,自动转化,不用另行编写MR代码。

25. JVM研究

GC垃圾回收机制部分

类加载部分

java类装载到JVM中有两种方式,隐式装载(比如new对象的时候),显式装载。
常用以下有四种classLoader

  1. BootStrap ClassLoader 引导类加载器 主要用于加载 /jre/lib、/jre/classes目录下的核心类库。这是最顶层的一个加载器,使用C++编写的。
  2. Extention ClassLoader 扩展类加载器 负责加载/JAVA_HOME/lib/ext/类库
  3. Application ClassLoader 应用类加载器 主要负责加载CLASSPATH下的类库和我们自己的java代码编译出来的class文件。
    除了引导加载器获取不到外(因为是用C++写的),其他的加载器我们都能通过代码查询到。
  4. 自定义加载器 需要继承classloader类
    public class Test_ClassLoader {
     public static void main(String[] args){
         System.out.println(Test_ClassLoader.class.getClassLoader());
         System.out.println(Test_ClassLoader.class.getClassLoader().getParent());
         System.out.println(Test_ClassLoader.class.getClassLoader().getParent().getParent());
     }
    }
    outout:
    sun.misc.Launcher$AppClassLoader@58644d46
    sun.misc.Launcher$ExtClassLoader@4554617c
    null
    Process finished with exit code 0
    一份java源码从产生到被运行的流程
  5. 首先.java文件只有编译成class字节码文件之后才能被类加载器读取,加载到JVM中。
  6. 检查类是否被加载,从上往下找。
  7. 装载:导入class文件
  8. 检查文件的是否有错,分析文件,给静态变量分配空间。
  9. 初始化,主要是静态变量,静态代码块的初始化
#面经#
全部评论
幂等不是在http请求做的吧,一般是后台开发时根据业务需求控制
点赞 回复 分享
发布于 2018-05-08 06:09
post不是安全的么?
点赞 回复 分享
发布于 2018-05-08 15:40

相关推荐

12-16 21:59
东北大学 Java
水杉1:我评估了仨月了
点赞 评论 收藏
分享
11-15 18:39
已编辑
西安交通大学 Java
全村最靓的仔仔:卧槽,佬啥bg呢,本也是西交么
点赞 评论 收藏
分享
小破站_程序员YT:听劝就换赛道, 算法上岸你想想就可以了,而且你求职地点还是在长沙。其次你这个项目其实意义不大,项目最好是写两个。然后就是你的简历工程词汇太少,全是一些语言名词。琢磨不到你的代码量。 你是25届,秋招基本结束,如果目前0offer,剩下的就是春招,按照你的语言,最快就是搞Python,然后就是考虑Qt.其他的你就不用想了,这么短的时间里面要去学习一门新语言和准备新项目太难了。
点赞 评论 收藏
分享
评论
点赞
55
分享
牛客网
牛客企业服务