Java面试题一
前言
前段时间面试Java工程师实习,由于Java八股文准备不够充分,在笔试就挂了,面试官还挺好,给我讲解了下。我觉得第一题还是很重要的,听说很多面试官都喜欢用String来开场,第九题和Maven相关的,没读懂题目,也记不太清了。希望这九个题对大家能有所帮助,有问题大家可以一起讨论,我这也有更全一点的,需要的可以联系我。
一、String、StringBuffer、StringBuilder的区别,线程是否安全,效率,使用场景情况?
1.String
String类是不可变的字符序列,String对象一旦创建,其内容就不能被改变,每次对String进行修改操作,都会生成一个新的String对象,并不会改变原来对象。
String设计为不可变的原因有以下几点:
1.线程安全性:不可变对象在多线程环境下是安全的,不需要额外的同步机制;
2.哈希缓存:String对象的哈希值在第一次计算后会缓存起来,提高查找速度;
3.安全性:在很多场景下,String对象需要被共享和传递,不可变性可以防止被意外修改。
2.StringBuffer
StringBuffer类在Java中是可变字符序列,与String不同,StringBuffer对象是在原有对象的基础上进行修改;StringBuffer中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的,对所有修改方法进行同步处理,确保在多线程环境下使用时不会出现数据不一致的问题。
3.StringBuilder
StringBuilder类也是可变字符序列,StringBuilder与StringBuffer的区别在于其并不是线程安全的,所有的方法都没有进行同步处理;StringBuilder提供一种在单线程环境下更高效的、可变的字符串操作类,因为没有同步开销,所以在性能上比StringBuffer更高效。
使用场景
1.String:String适用于字符串内容不会频繁修改的场景,如字符串常量、配置参数、日志信息等;
2.StringBuffer:StringBuffer适用于字符串内容频繁修改,并且在多线程环境下的使用场景,如需要在多线程中构建长字符串时;
3.StringBuilder:StringBuilder适用于字符串内容需要频繁修改,但在单线程环境下使用的场景,如在单线程的应用或方法内部构建长字符串时。
二、输出下面程序结果: 2021-10-2
public class test {
public static void main(String[] args) {
List<String> list = Arrays.asList("2021-10-21 17:31","2021-10-22","2021-10-23");
System.out.println(maxList(list));
}
public static String maxList(List<String> list) {
String s = list.get(0);
for (int i=1;i<list.size();i++) {
for (int j=0;j<s.length()&&j<list.get(i).length();j++) {
if (s.charAt(j) != list.get(i).charAt(j)) {
s = s.substring(0,j);
}
}
if (s == "") {
return s;
}
}
return s;
}
}
三、实现单例模式
这里写两种:懒汉模式DCL 和 静态内部类
//单例模式的懒汉实现5--线程安全
//通过设置同步代码块,使用DCL双检查锁机制
//使用双检查锁机制成功的解决了单例模式的懒汉实现的线程不安全问题和效率问题
//DCL 也是大多数多线程结合单例模式使用的解决方案
// 在定义singletonLazy的时候用到了volatile关键字,这是为了防止指令重排序的
public class SingletonLazy5 {
private static volatile SingletonLazy5 singletonLazy;
private SingletonLazy5() {
}
public static SingletonLazy5 getInstance() {
try {
if (null == singletonLazy) {
// 模拟在创建对象之前做一些准备工作
Thread.sleep(1000);
synchronized (SingletonLazy5.class) {
if(null == singletonLazy) {
singletonLazy = new SingletonLazy5();
}
}
}
} catch (InterruptedException e) {
// TODO: handle exception
}
return singletonLazy;
}
}
//使用静态内部类实现单例模式--线程安全
public class SingletonStaticInner {
private SingletonStaticInner() {
}
private static class SingletonInner {
private static SingletonStaticInner singletonStaticInner = new SingletonStaticInner();
}
public static SingletonStaticInner getInstance() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return SingletonInner.singletonStaticInner;
}
}
四、使用jdk8的stream对字符串数组去重
List<String> list = Arrays.asList("a","a","b","c");
public static void main(String[] args) {
List<String> list = Arrays.asList("a","a","b","c");
// 去重
// 方法一
list.stream().distinct().forEach(System.out::println);
// 方法二
Set<String> set = list.stream().collect(Collectors.toSet());
System.out.println(set);
}
五、写一个程序,获取字符串中不重复的最大字串长度
例1 String: "abcabs"
结果:长度为4 cabs
例2 String: "abawkw"
结果:长度为4 bawk
例3 String: "wksiswabac"
结果:长度为5 iswab
public class MaxUniqueSubstring {
public static String findMaxUniqueSubstring(String s) {
if (s == null || s.length() == 0) {
return "";
}
int maxLen = 0; // 最大不重复子串的长度
int start = 0; // 滑动窗口的起始位置
int end = 0; // 滑动窗口的结束位置
String maxSubstring = ""; // 最大不重复子串
Set<Character> charSet = new HashSet<>(); // 用于存储当前窗口中的字符
while (end < s.length()) {
char c = s.charAt(end);
// 如果当前字符不在集合中,则添加到集合中,并尝试扩展窗口
if (!charSet.contains(c)) {
charSet.add(c);
// 如果当前窗口的长度大于已知的最大长度,则更新最大长度和对应的子串
if (end - start + 1 > maxLen) {
maxLen = end - start + 1;
maxSubstring = s.substring(start, end + 1);
}
end++;
} else {
// 如果当前字符已经在集合中,则需要缩小窗口
charSet.remove(s.charAt(start));
start++;
}
}
return maxSubstring;
}
public static void main(String[] args) {
String testStr1 = "abcabs";
System.out.println("Length: " + findMaxUniqueSubstring(testStr1).length() + " Substring: " + findMaxUniqueSubstring(testStr1));
String testStr2 = "abawkw";
System.out.println("Length: " + findMaxUniqueSubstring(testStr2).length() + " Substring: " + findMaxUniqueSubstring(testStr2));
String testStr3 = "wksiswabac";
System.out.println("Length: " + findMaxUniqueSubstring(testStr3).length() + " Substring: " + findMaxUniqueSubstring(testStr3));
}
}
六、输出下面程序结果 D
A:2 B: 1 C:0 D:无法编译
public class Demo {
public static void main(String[] args) {
Demo demo = new Demo();
demo.aMethod();
System.out.println(demo.aMethod());
}
public Integer aMethod() {
static Integer a = 0;
a++;
return a;
}
}
七、写出如下结果语句
user表
userId | username | firstname |
---|---|---|
1 | 小米 | 张 |
2 | 小明 | 王 |
address表
id | userId | city |
---|---|---|
1 | 2 | 湖北 |
2 | 3 | 武汉 |
结果
firstname | username | city |
---|---|---|
张 | 小米 | (Null) |
王 | 小明 | 湖北 |
语句:SELECT firstname,username,city FROM user
LEFT JOIN address on user
.userId=address.userId
八、从用户信息表中提取用户名,并将性别转换为可读文本形式
SELECT username,
CASE
WHEN sex=1 THEN '男'
ELSE '女'
END as sexx
FROM `user_info`
九、Maven中管理版本,A->B->C->D(版本为1.1)
没读懂题目,记不清了
十、Mysql优化
(1)尽量选择较小的列
(2)将where中用的比较频繁的字段建立索引
(3)select子句中避免使用‘*’
(4)避免在索引列上使用计算、not in 和<>等操作
(5)当只需要一行数据的时候使用limit 1
(6)保证单表数据不超过200W,适时分割表。针对查询较慢的语句,可以使用explain 来分析该语句具体的执行情况。
(7)避免改变索引列的类型。
(8)选择最有效的表名顺序,from字句中写在最后的表是基础表,将被最先处理,在from子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。
(9)避免在索引列上面进行计算。
(10)尽量缩小子查询的结果