大数据面试题

Java部分:
1.什么是构造函数,构造代码块,静态代码块?分别的做用是什么?三者的顺序
构造函数是类用来建立对象使用的一种函数能够有有参构造函数也能够有无参构造函数
构造代码块的做用和构造函数相似能够完成类中的成员变量进行初始化也能够调用成员方法
静态代码块属于类的,静态代码块能够随着类的加载而加载能够初始化中的静态成员变量,也
能够在链接JBCD时用于读取文件中的链接信息
先执行静态代码块 在执行构造代码块 最后执行构造方法java

2.double和Double的区别?
double是基本数据类型,值会存储在栈中而且初始值是0.0,不能存在集合中
Double是包装类即double的引用类型,值会存储在堆中初始值是null,能够替代double存储 集合中node

3.2<<3等于多少
16mysql

4.判断字符串为空时如何避免空指针异常?
String str=null;
if(str == null || str.isEmpty())来进行判断linux

5.什么是重载和重写?
重载:是面向对象中多态特性的一种体现,即方法名相同形参列表不一样(参数,个数,顺序)知足其中一个条件便可
重写:是面向对象中继承特性的一种体现,即父类中所提供的方法没法知足子类需求时,子类能够实现和父类同样的方法即为重写,可是fianl,private,static修饰的方法没法重写算法

6.实现线程的三种方式?
继承Thread类,并复写run方法,建立该类对象,调用start方法开启线程。
实现Runnable接口,复写run方法,建立Thread类对象,将Runnable子类对象传递给Thread类对象。调用start方法开启线程。
建立FutureTask对象,建立Callable子类对象,复写call(至关于run)方法,将其传递给FutureTask对象(至关于一个Runnable)
7.Thread类中的start()和run()方法的区别?
用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。经过调用Thread类的 start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并无运行,一旦获得cpu时间片,就开始执行run()方法,这里方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。spring

8.final修饰的方法能够被继承/重载/重写吗?
final修饰的方法能够继承和重载,可是不能重写sql

9.遍历二叉树的方式有哪些?选择一种方式用程序实现?
二叉树遍历分为三种先序遍历
首先访问根,再先序遍历左子树,最后先序遍历右子树 根 --> 左 -- > 右
无序中序遍历首先中序遍历左子树,再访问根,最后中序遍历右子树 左 --> 根 --.> 右
升序后序遍历首前后序遍历左子树,再后序遍历右子树,最后访问根 左 --> 右 --> 跟数据库

左-->根-->右排序
public class BinaryTree {
private Node root;//节点
//添加节点
public void add(int data) {
if(root == null) {
root = new Node(data);
}else {
root.addNode(data);
}
}
public void printBinaryTree() {
root.print();
}后端

class Node{
      private int data;//数据
      private Node left; //左
      private Node right; //右
     public Node(int data) {
         this.data = data;
     }
     //添加节点(左/右)
     public void addNode(int data) {
         if(this.data > data) {
             if(this.left == null) {
                 this.left = new Node(data);
             }else {
                 //递归
                 this.left.addNode(data);
             }
         }else {
             if(this.right == null) {
                 this.right =  new Node(data);
             }else {
                 this.right.addNode(data);
             }
         }
     }
     //左 --> 根 ---> 右
     public void print() {
         if(this.left != null) {
             this.left.print();
         }
         System.out.print(this.data+"->");
         if(this.right != null) {
             this.right.print();
         }
     }
  }

}
public class Test {
public static void main(String[] args) {
BinaryTree bt = new BinaryTree();
bt.add(8);
bt.add(3);
bt.add(10);
bt.add(6);
bt.add(7);
bt.add(14);
bt.add(13);
bt.add(2);
bt.printBinaryTree();
}
}设计模式

10.java常见的排序方式有哪些?选择一种实现?
冒泡排序复杂度为O(nn),插入排序复杂度为O(nn),堆排序复杂度为nlog2(n)
快速排序复杂度为nlog2(n),归并排序复杂度为nlog2(n)
冒泡排序:
public class maopao {
public static void main(String[] args) {
int[] numbers = {10,12,2,3,5,78,6,21,99,88};
for(int j =0; j<numbers.length-1; j++){
for(int i = 0; i<numbers.length-1-j;i++){
int temp = 0;
if (numbers[i]>numbers[i+1]){
temp = numbers[i+1];
numbers[i+1] = numbers[i];
numbers[i] = temp;
}
}
}
}
}

11.什么是反射?如何经过反射访问私有字段?
JAVA反射机制是在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.因此先要获取到每个字节码文件对应的Class类型的对象.
能够用getDeclaredField方法而且须要开启权限setAccessible(true)

12.常见的排序及复杂度,实现快排算法
冒泡排序复杂度为O(nn),插入排序复杂度为O(nn),堆排序复杂度为nlog2(n)
快速排序复杂度为nlog2(n),归并排序复杂度为nlog2(n)
快排算法:

public class QickSort {
public static void main(String[] args) {
int[] numbers = {10,12,2,3,5,78,6,21,99,88};
int len = numbers.length;
//若是数组大于2的时候才开始排序
if(len>1){
quickSort(numbers,0,len-1);
}
System.out.println(Arrays.toString(numbers));
}
public static void quickSort(int[] list, int low, int high) {
if(low < high){
int middle = getMiddle(list, low, high);
quickSort(list, low, middle - 1);
quickSort(list, middle + 1, high);
}
}
public static int getMiddle(int[] list, int low, int high) {
int temp = list[low];
while(low < high){
while(low < high && temp <= list[high]){
high--;
}
temp>=list[high]
list[low] = list[high];
while(low < high && list[low] <= temp){
low++;
}
list[low]>temp
list[high] = list[low];
}
list[low] = temp;
return low;
}
}

13.题目:实现Fibonacci(即斐波那契额)数列
public class Demo {
public static int f(int n) throws Exception {
if(n==0){
throw new Exception("参数错误!");
}
if (n == 1 || n == 2) {
return 1;
} else {
return f(n-1)+f(n-2);//本身调用本身
}
}
public static void main(String[] args) throws Exception {
for (int i = 1; i <=10; i++) {
System.out.print(f(i)+" ");
}
}
}

14.常见的设计模式,任选模式一种模模式代码的实现

单例,模板,工厂,装饰者,适配器,代理,观察者等设计模式
public class HungrySingle {
private static HungrySingle instance = new HungrySingle();
private HungrySingle() {
}
public static HungrySingle getInstance() {
return instance;
}
}

15.简述java线程池,并说明线程安全的解决思路
所谓线程池,就是将多个线程放在一个池子里面(所谓池化技术),而后须要线程的时候不是建立一个线程,而是从线程池里面获取一个可用的线程,而后执行咱们的任务。线程池的关键在于它为咱们管理了多个线程,咱们不须要关心如何建立线程,咱们只须要关系咱们的核心业务,而后须要线程来执行任务的时候从线程池中获取线程。任务执行完以后线程不会被销毁,而是会被从新放到池子里面,等待机会去执行任务。
 一个线程池包括如下四个基本组成部分:
                一、线程池管理器(ThreadPool):用于建立并管理线程池,包括 建立线程池,销毁线程池,添加新任务;
                二、工做线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,能够循环的执行任务;
                三、任务接口(Task):每一个任务必须实现的接口,以供工做线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工做,任务的执行状态等;
                四、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。

解决线程安全问题的思路是消除产生线程安全问题的环境:
消除共享数据:成员变量与静态变量多线程共享,将这些全局变量转化为局部变量,局部变量存放在栈,线程间不共享,就不存在线程安全问题产生的环境了。消除共享数据的不足:若是须要一个对象采集各个线程的信息,或者在线程间传递信息,消除了共享对象就没法实现此目的。
使用线程同步机制:给读写操做同时加锁,使得同时只有一个线程能够访问共享数据。若是单单给写操做加锁,同时只有一个线程能够执行写操做,而读操做不受限制,容许多线程并发读取,这时就可能出现不可重复读的状况,如一个持续时间比较长的读线程,相隔较长时间读取数组同一索引位置的数据,正好在这两次读取的时间内,一个线程修改了该索引处的数据,形成该线程从同一索引处先后读取的数据不一致。是同时给读写加锁,仍是只给写加锁,根据具体需求而定。同步机制的缺点是下降了程序的吞吐量。
创建副本:使用ThreadLocal为每个线程创建一个变量的副本,各个线程间独立操做,互不影响。该方式本质上是消除共享数据思想的一种实现。
使用synchronized或lock来完成加锁处理

16.什么是cookie,做用是什么?cookie和session的区别与联系
cookie是存在于客户端(浏览器)。
cookie的使用是由浏览器按照必定的原则在后台自动发送给服务器的。浏览器检查全部存储的cookie,若是某个cookie所声明的做用范围大于等于将要请求的资源所在的位置,则把该cookie附在请求资源的HTTP请求头上发送给服务器。
cookie的内容主要包括:名字,值,过时时间,路径和域。其中路径与域一块儿构成cookie的做用范围。若不设置过时时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失

Session是另外一种记录客户状态的机制,不一样的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录
  在服务器上。这就是Session。客户端浏览器再次访问时只须要从该Session中查找该客户的状态就能够了。
  每一个用户访问服务器都会创建一个session,那服务器是怎么标识用户的惟一身份呢?事实上,用户与服务器创建链接的同时,服务器会自动为其分配一个SessionId

总结
一、cookie数据存放在客户的浏览器上,session数据放在服务器上。
二、cookie不是很安全,别人能够分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
三、session会在必定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
四、单个cookie保存的数据不能超过4K,不少浏览器都限制一个站点最多保存20个cookie。
五、能够考虑将登录信息等重要信息存放为session,其余信息若是须要保留,能够放在cookie中。

17.简述spring隔离级别与传播行为
spring 的事务传播行为: 
Spring在TransactionDefinition接口中规定了7种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播:
  PROPAGATION_REQUIRED:若是当前没有事务,就新建一个事务,若是已经存在一个事务中,加入到这个事务中。这是最多见的选择。
  PROPAGATION_SUPPORTS:支持当前事务,若是当前没有事务,就以非事务方式执行。
  PROPAGATION_MANDATORY:使用当前的事务,若是当前没有事务,就抛出异常。
  PROPAGATION_REQUIRES_NEW:新建事务,若是当前存在事务,把当前事务挂起。
  PROPAGATION_NOT_SUPPORTED:以非事务方式执行操做,若是当前存在事务,就把当前事务挂起。
  PROPAGATION_NEVER:以非事务方式执行,若是当前存在事务,则抛出异常。
  PROPAGATION_NESTED:若是当前存在事务,则在嵌套事务内执行。若是当前没有事务,则执行与PROPAGATION_REQUIRED相似的操做。

Spring 的隔离级别
SERIALIZABLE:最严格的级别,事务串行执行,资源消耗最大;
REPEATABLE_READ:保证了一个事务不会修改已经由另外一个事务读取但未提交(回滚)的数据。避免了”脏读取”和”不可重复读取”的状况,可是带来了更多的性能损失。
READ_COMMITTED:大多数主流数据库的默认事务等级,保证了一个事务不会读到另外一个并行事务已修改但未提交的数据,避免了”脏读取”。该级别适用于大多数系统。
Read_UNCOMMITTED:保证了读取过程当中不会读取到非法数据

18.简述常见先后端服务框架
SpringMVC,Spring,Mybatis,Dubbo,RabbitMQ,Redis

19.不使用循环条和件语句实现1+2+3+...n
public static int sum(int n) {
int sum = n;
boolean isContinue = (n > 0) && (sum += sum(--n)) > 0;
return sum;
}

public static void main(String[] args) {
    int result = sum(5);
    System.out.println(result);

}

Linux部分:
1.linux如何查看系统负载,内存.硬盘使用状况
负载:top -c
内存:free -h
磁盘:df -h

2.linux > 和 >> 的区别,经常使用查看日志命令

是定向输出到文件,若是文件不存在,就建立文件;若是文件存在,就将其清空;通常咱们备份清理日志文件的时候,就是这种方法:先备份日志,再用>,将日志文件清空(文件大小变成0字节)。

这个是将输出内容追加到目标文件中。若是文件不存在,就建立文件;若是文件存在,则将新的内容追加到那个文件的末尾,该文件中的原有内容不受影响。
查看日记命令
tail,head,cat,sed,more,less

Mysql部分:
1.musql5.x默认使用的引擎?对应的锁机制?
InnoDB做为默认存储引擎,InnoDB做为支持事务的存储引擎,拥有相关的RDBMS特性:包括ACID事务支持,参考完整性(外健),灾难恢复能力等特性
行锁:开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的几率低,并发度高

2.什么查询条件下索引会失效?
若是条件中有or,即便其中有条件带索引也不会使用(这也是为何尽可能少用or的缘由)
对于多列索引,不是使用的第一部分,则不会使用索引
like查询是以%开头(以%结尾是能够的)
若是列类型是字符串,那必定要在条件中将数据使用引号引用起来,不然不使用索引
若是mysql估计使用全表扫描要比使用索引快,则不使用索引

3.having和where的区别
“Where”是一个约束声明,在查询数据库的结果返回以前对数据库中的查询条件进行约束,即在结果返回以前起做用,且where后面不能使用“聚合函数”;
“Having”是一个过滤声明,所谓过滤是在查询数据库的结果返回以后进行过滤,即在结果返回以后起做用,而且having后面可使用“聚合函数”。

4.union all和 union的区别
union和union all的区别是,union会自动压缩多个结果集合中的重复结果,而union all则将全部的结果所有显示出来,无论是否是重复。
Union由于要进行重复值扫描,因此效率低。若是合并无刻意要删除重复行,那么就使用Union All

5.什么是左链接?
左链接是以左表为基础Left join即左链接,是以左表为基础,根据ON后给出的两表的条件将两表链接起来。结果会将左表全部的查询信息列出,而右表只列出ON后条件与左表知足的部分。左链接全称为左外链接,是外链接的一种

6.请用一个sql语句返回两张表的差集
select * from tab1 where id not in (select id from tab2)

select table1.id from table1 left join table2 on table1.id=table2.id where table2.id is null;

Hadoop部分:
1.一般状况下集群模式的瓶颈在哪?
首先,瓶颈通常是指在总体中的关键限制因素,磁盘IO是指数据往磁盘读写,如今的科技速度最快的属固态硬盘了,读的速度很大有1G/秒左右,可是写入速度最快几百兆/秒,集群中数据在cpu和内存之间速度快的能够忽略,处理速度也能够忽略,相对这些速度,磁盘读写就显得慢了,旁贷一下如今好一点的数据库oracle存储数据都是写日志先暂存而后等机器空闲再写入到磁盘,这些都是为了提升效率,否则执行一条操做等半天

2.SecondaryNameNode的做用是什么?
SecondaryNameNode它的职责是合并NameNode的edit logs到fsimage文件中
首先,SecondaryNameNode定时到NameNode去获取edit logs,并更新到fsimage上。一旦它有了新的fsimage文件,SecondaryNameNode将其拷贝回NameNode中。NameNode在下次重启时会使用这个新的fsimage文件,从而减小重启的时间。
Secondary NameNode的整个目的是在HDFS中提供一个检查点。它只是NameNode的一个助手节点。这也是它在社区内被认为是检查点节点的缘由。

3.请用map,reduce实现wordCount?
public class WordCount {
public static class MyMapper extends Mapper<Object, Text, Text, IntWritable>{
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
@Override
protected void map(Object key, Text value,Context context)
throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
context.write(word, one);
}
}
}
public static class MyReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
private IntWritable result = new IntWritable();
@Override
protected void reduce(Text key, Iterable values, Context context)
throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(MyMapper.class);
job.setCombinerClass(MyReducer.class);
job.setReducerClass(MyReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true)?0:1);
}

}

Spark部分:
1.ElasticSearch如何避免脑裂?
修改集群中每一个节点的配置文件(elasticsearch.yml)参数 discovery.zen.minimum_master_nodes,这个参数决定了主节点选择过程当中最少须要多少个 master 节点,默认配置是1。
一个基本原则是这里须要设置成 N/2+1,N 是集群中节点的数量。
修改集群中每一个节点的配置文件(elasticsearch.yml)参数 discovery.zen.ping.timeout,默认值是3,决定节点之间网络通讯的等待时间。
修改集群中每一个节点的配置文件(elasticsearch.yml)参数 discovery.zen.ping.unicast.hosts,把集群中可能成为主节点的机器节点都配置到这个参数中。

2.ElasticSearch中:match和term区别?
term是表明彻底匹配,也就是精确查询,搜索前不会再对搜索词进行分词,因此搜索词必须是文档分词集合中的一个
match查询会先对搜索词进行分词,分词完毕后再逐个对分词结果进行匹配,所以相比于term的精确搜索,match是分词匹配搜索,match搜索还有两个类似功能的变种,一个是match_phrase,一个是multi_match

3.kafak在高并发的状况下,如何避免消息丢失和消息重复? 消息丢失解决方案: 首先对kafka进行限速, 其次启用重试机制,重试间隔时间设置长一些,最后Kafka设置acks=all,即须要相应的全部处于ISR的分区都确认收到该消息后,才算发送成功 消息重复解决方案: 消息可使用惟一id标识  生产者(ack=all 表明至少成功发送一次)  消费者 (offset手动提交,业务逻辑成功处理后,提交offset)  落表(主键或者惟一索引的方式,避免重复数据)  业务逻辑处理(选择惟一主键存储到Redis或者mongdb中,先查询是否存在,若存在则不处理;若不存在,先插入Redis或Mongdb,再进行业务逻辑处理)