7

1.String是不可变的

public class Foo {
    public static void main(String[] args) {
        String strValue = "ABCDEFG"; 
        strValue.substring(3); 
        strValue.concat("123");
        System.out.println(strValue);            
        String value = new String ("ABCDEFG");
        System.out.println(strValue == value);
    }
}

答案:

ABCDEFG
false

解析:
String是final的,因此不能修改,所以诸如substring()、concat()这些方法,不会修改strValue变量存储的值。

字符串会存在字符串常量池。new String("ABCDEFG")先在常量池中查找,若没有则创建"ABCDEFG",而后通过new在堆内存中创建对象,把"ABCDEFG"拷贝赋值。故创建常量池和堆内存中两个对象,两个对象的地址值不一样。

2.字符串比较,代码打印结果是什么?

String s1="abc";
String s2="abc";
System.out.println(s1==s2);
System.out.println(s1.equals(s2));

答案:

true
true

解析:

先在常量池中创建"abc",变量s1指向它,而后在创建s2时,由于常量池中已经存在"abc",只需s2指向它,而不需要再创建。因此s1和s2指向的内存地址是一样的,所以第一个结果为true。而equals方法经过重写后操作为"比较此字符串内容时候相同"所以第二个结果为true。

3.String s1=new String("abc")创建了几个对象?

解析:

new String("abc")先在常量池中查找,若没有则创建"abc",而后通过new在堆内存中创建对象,把"abc"拷贝赋值。String定义为初始化一个新创建的 String 对象,表示一个与该参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的一个副本。故创建常量池和堆内存中两个对象,两个对象的地址值不一样。

4.判断字符串是否相等

String s1=new String("abc");
String s2="abc";
System.out.println(s1==s2); 
System.out.println(s1.equals(s2));

答案:

false
true

解析:
==比较的是内存地址,String的equals方法重写了Object的equals方法,String的equals方法比较的是字符串的内容是否相同。

5.字符串的编译期优化

String s1="a"+"b"+"c";
String s2="abc";
System.out.println(s1==s2);
System.out.println(s1.equals(s2));

答案:

true
true

解析:
本题主要考察java中常量优化机制,编译时s1已经成为“abc”在常量池中查找创建,s2不需要再创建。

6.字符串的对象

String s1="ab";
String s2="abc";
String s3=s1+"c";
System.out.println(s3==s2);
System.out.println(s3.equals(s2));

答案:

false
true

解析:
Java 语言提供对字符串串联符号(”+”)和其他对象到字符串的转换的特殊支持。字符串串联是通过 StringBuilder(或 StringBuffer)类及其 append 方法实现的,字符串转换是通过 toString 方法实现的。在本题中,先在常量池中创建”ab“,地址指向s1,再创建”abc”,指向s2。对于s3,先创建StringBuilder(或 StringBuffer)对象,通过append连接得到“abc”,再调用toString()转换得到的地址指向s3。故(s3==s2)为false.

7.冒泡排序

数组元素从左至右两两比较,较大值移到右边,每一趟比较后,最大值会移到最右边。

public void bubbleSort(int[] arr){
    int n = arr.length - 1;
    for(int i = 0; i < n; i++){//比较多少趟
        for(int j = 0; j < n - i; j++){//每一趟比较右边都多一个最大值,因此要-i
            if( arr[j] > arr[j+1] ){
                //交换位置
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }           
        }
    }
}

8.选择排序

每次从数组中选择最小的元素,置换到有序组中。

public void selectSort(int[] arr){
    int n = arr.length;
    for(int i = 0; i < n; i++){
        int min = i;//初始化最小值的索引
        for(int j = i+1; j < n; j++){
            if(arr[j]<arr[min]){
                min = j;//记录最小值的索引
            }
        }
        //交换值
        int temp = arr[i];
        arr[i] = arr[min];
        arr[min] = temp;
    }
}

9.插入排序

逻辑上把数组分成有序组待插入组,每次从待插入组取出一个元素,在有序组中找到插入位置然后插入。

public void insertSort(int[] arr){
    int n = arr.length;
    for(int i = 1; i < n; i++){         //遍历待插入组
        int temp = arr[i];              //待插入数
        int j = i - 1;                  //有序组最后一个元素的索引
        while(j>=0 && temp<arr[j]){     //遍历有序组,如果待插入数小于当前比较的有序组的数x
            arr[j+1] = arr[j];          //有序组的数x的值往右移动一位,腾出插入位置
            j--;                        //下标移动到下一个待比较的有序组的数
        }
        arr[j+1] = temp;                //遍历一趟有序组后j+1表示的下标,就是temp应插入的位置
    }
}

10.二分查找

public int binarySearch(int[] arr, int key){
    int lo = 0;
    int hi = arr.length - 1;
    while(lo<=hi){
        int mid = lo + (hi-lo)/2;
        if(key < arr[mid]) hi = mid - 1;
        else if(key > arr[mid]) lo = mid + 1;
        else return mid;        
    }
    return -1;
}

11.单例模式(饿汉式)

public class Singleton{

    private static final Singleton instance = new Singleton();
        
    private Singleton(){
    } 
    
    public static Singleton getInstance(){
        return instance;
    }

}

12.单例模式(枚举式)

public enum Singleton{
    
    INSTANCE;
    
    private String name;
    
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
}

13.简述String、StringBuilder、StringBuffer的区别

---- ----
String 字符串常量
StringBuffer 字符串变量 线程安全
StringBuilder 字符串变量 非线程安全

14.简述Zookeeper的角色和原理

15.简述Java中List、Set、Map、Queue之间的区别

集合类型 特点
List 元素有序,可重复
Set 元素无序,不可重复
Map 双列集合,一次存一对键值对,键不能重复
Queue 元素先进先出,不允许随机访问队列中的元素

List的实现类:

  • ArrayList:数组实现, 查找快, 增删慢。由于是数组实现, 在增和删的时候会牵扯到数组增容, 以及拷贝元素。所以慢。数组是可以直接按索引查找, 所以查找时较快。
  • LinkedList:链表实现, 增删快, 查找慢。由于链表实现, 增加时只要让前一个元素记住自己就可以, 删除时让前一个元素记住后一个元素, 后一个元素记住前一个元素。 这样的增删效率较高。但查询时需要一个一个的遍历, 所以效率较低。
  • Vector:和ArrayList原理相同, 但线程安全, 效率略低和ArrayList实现方式相同, 但考虑了线程安全问题, 所以效率略低。

Set的实现类:

  • HashSet:线程不安全,存取速度快。底层是以hash表实现的
  • TreeSet:红-黑树的数据结构,默认对元素进行自然排序(String)。如果在比较的时候两个对象返回值为0,那么元素重复。
  • LinkedHashSet:会保存元素插入的顺序

Map的实现类:

  • HashMap:底层是哈希表数据结构,线程不安全。可以存入null键、null值。要保证键的唯一性,需要覆盖hashCode方法,和equals方法。
  • LinkedHashMap:基于哈希表又融入了链表,所以Map集合进行增删提高效率。
  • TreeMap:底层是二叉树数据结构。可以对map集合中的键进行排序。需要使用Comparable或者Comparator进行比较排序。return 0,来判断键的唯一性。
  • HashTable:底层是哈希表数据结构,线程是同步的,不可以存入null键,null值。效率较低,被HashMap 替代

Queue的实现类:

  • PriorityQueue:保存队列元素的顺序并不是按照加入队列的顺序,而是按照队列元素的大小进行重新排序,这点从它的类名也可以看出来
  • Deque:代表一个"双端队列",双端队列可以同时从两端来添加、删除元素,因此Deque的实现类既可以当成队列使用、也可以当成栈使用。
  • ArrayDeque:是一个基于数组的双端队列,和ArrayList类似,它们的底层都采用一个动态的、可重分配的Object[]数组来存储集合元素,当集合元素超出该数组的容量时,系统会在底层重新分配一个Object[]数组来存储集合元素
  • LinkedList:链表实现, 增删快, 查找慢。

16.请说说JVM加载class文件的原理和机制

17.Java中实现多态有哪些方式?

18.请写出3个java.util.concurrent包中的类,并简述它们的用户和应用场景

19.你在使用spark的过程中遇到了哪些问题,怎么解决?

20.写出删除hdfs上/tmp/hello目录的命令

21.谈谈你在工作中遇到的一个最难的问题,并说出解决方法和结果。

22.简述synchronized和java.util.concurrent.locks.Lock的异同点

23.编程:假设有n个人围成一个圈...

编程题:假设有n个人围成一个圈,从第一个人开始报数,数到第m个人出列,然后从出列的下一个人开始报数,数到第m个人又出列,...,如此反复知道所有人全部出列为止。设n个人的编号为1,2,3...,n,打印出出列的顺序。

24.char类型变量能存储中文吗?

char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。

25.一个大型网站用一个日志表来记录用户的操作行为,每天产生上百万条记录。另有一个调度程序定时清除7天前的数据(每天3:00)。请用shell脚本写出调度程序的伪代码。

26.一张用户表有1000万条记录,主键为自增id,从中取出10条随机记录,如何实现?

27.写出Linux中查看进程的命令

28.说说你知道的查找消耗比较大的sql的方法

29.linux中如何查看一个监听8080端口的进程

30.分析日志文件,要求统计出响应时间超过100ms的请求及其个数,写出相应的shell命令。文件内容如下,字段依次为:时间戳、请求、响应时间。

20170718000000`addCopy:39
20170718000000`select:16
20170718000000`info:250
20170718000000`info:201

31.linux上的一个文件file,内容格式为“时间,用户标识,页面”,请用shell命令统计出uv和pv

2017-10-01 01:11:30,uid001,page1
2017-10-01 01:35:21,uid001,page2
2017-10-01 04:22:17,uid002,page1
...

32.hdfs默认块大小是多少?

33.写出三个常用的spring或springboot注解,并说明其用途

34.有如下表,请写出sql。

name course score
张三 语文 70
李四 数学 90
李四 英语 88
王五 英语 95
... ... ...
  • 查询学生的姓名及平均分
  • 查询每门课程都>80分的学生的姓名

35.说说SpringBoot的加载机制

36.说说SpringCloud都有哪些组件,作用又是什么?

37.说说Redis有哪些持久化策略

38.MySQL查询慢的原因可能有哪些?

39.转发和重定向的区别

40.static和final可以写在什么位置?有什么区别

static

1)static主要用于修饰类的成员:成员变量、成员方法、内部类、代码块
当修饰成员变量时,成员变量可以通过类名来访问,也可以通过对象名来访问;
当修饰成员方法时,成员方法可以通过类名直接调用,也可以通过对象名来调用;
当修饰内部类时,内部类可以通过类名直接访问,也可以通过对象名来访问;

2)静态方法不能访问非静态成员(变量和方法)

3)静态方法不能使用this、super

4)静态的成员优先与对象的成员存在

final

5)final主要用于修饰类、成员变量、成员方法、局部变量

6)final修饰成员属性时,表示是一个常量,不能被修改。如果修饰的是基本数据类型,表示值不能被修改;如果修饰的是对象,表示引用值不能被修改。

7)final修饰类时,该类不能被继承。

8)final修饰方法时,该方法不能被重写。

9)final修饰局部变量时,该变量不能被修改。

static final
static和final可以一起使用,可简单理解成全局常量,static final的前后位置可以互换没有区别。
修饰变量时,表示一旦给值就不可修改,并且通过类名可以访问。
修饰方法时,表示不可重写,并且可以通过类名直接访问。

41.wait() 和 sleep()有什么区别?

wait():释放资源,释放锁。是Object的方法
sleep():释放资源,不释放锁。是Thread的方法

42.数据库的truncate、delete、drop有什么区别?

共同点:
都可以删除表数据

区别:

语句 举例 特性 特性
drop drop table users 删除表的数据和结构,释放空间 DDL语言,DDL语言都是自动提交的且不能回滚
truncate truncate table users 删除表的数据,保留结构,释放空间 DDL语言
delete delete from users (可带where子句) 删除表的数据,保留结构,不释放空间 DML语言,可回滚

空间是指:表和索引所占用的空间

其它:

  • 速度比较:drop > truncate > delete
  • 释放空间的测试:建个表含自增索引的,插入几条记录,然后truncate,再插入几条记录,会发现自增索引又从1开始。但是如果用delete的话,会发现所以不是从1开始的,而是接着最后删除的记录的自增id。
  • delete语句每次删除一行,很慢
  • drop还可以用来删除数据库

43.说说工作中遇到过什么异常

NullPointerException,IndexOutOfBoundException,StackOverflowException

44.什么样的情况会造成内存泄漏,请举一些例子。

45.接口和抽象类的异同。

共同点:
1)接口和抽象类都不能实例化
2)接口和抽象类都可以有抽象方法,它们的子类必须实现抽象的方法

不同点:
3)接口只能有抽象方法,但抽象类可以同时有抽象方法和普通的方法
4)接口只能有静态常量,但抽象类可以有静态常量和成员变量。
5)接口不能有构造器或构造代码块,但抽象类可以有。

46.列出各个部门中工资高于本部门的平均工资的员工数和部门号,并按部门号排序

/*创建表*/
create table employee02(
    id int primary key auto_increment,
    name varchar(50),
    salary bigint,
    deptid int
);

/*插入测试数据*/
 insert into employee02 values
(null,'zs',1000,1),
(null,'ls',1100,1),
(null,'ww',1100,1),
(null,'zl',900,1) ,
(null,'xl',1000,2), 
(null,'sx',900,2) ,
(null,'df',1000,2) , 
(null,'fh',1100,2);


/*查询语句*/
/*单纯查询每个部门的平均工资*/
select avg(salary) from employee02 group by deptid;

/*版本1,使用子查询实现*/
SELECT a.id,a.name,a.salary,a.deptid 
FROM employee02 a WHERE a.salary > 
(SELECT AVG(salary) FROM employee02 b WHERE b.deptid = a.deptid);

/*版本2*/
SELECT a.name,a.salary,a.deptid 
FROM employee02 a,
(SELECT deptid,AVG(salary) avgsal FROM employee02 GROUP BY deptid ) b
WHERE a.deptid = b.deptid AND a.salary > b.avgsal;

煲煲菜
1.5k 声望155 粉丝

世上本没有bug,坑的人多了,也便成了bug