目录
1. String、StringBuilder和StringBuffer的区别?
10. UNION和UNION ALL这两个关键字的区别和作用分别是什么?
12. 从前端页面到Java后台再到数据库,有一张表,表存在上百万条数据,从这三个层面,去做一个查询方面的优化,单表查询。
1. String、StringBuilder和StringBuffer的区别?
三者的区别如下:
-
String
对象是不可变的,即一旦创建,其内容就不能被改变。每次对String
进行修改操作(如拼接、替换等),都会生成一个新的String
对象。由于String
对象不可变,因此它是线程安全的,可以在多线程环境下安全使用,并且由于每次修改都会创建新的对象,String
在频繁修改字符串的场景下性能较差。 -
StringBuilder
是可变的,它允许在不创建新对象的情况下修改字符串内容,它不是线程安全的,它的方法没有同步机制,因此在多线程环境下使用时需要注意线程安全问题,由于不需要创建新对象,StringBuilder
在频繁修改字符串的场景下性能较好。 -
StringBuffer
也是可变的,它允许在不创建新对象的情况下修改字符串内容,StringBuffer
是线程安全的,它的方法都是同步的,因此在多线程环境下可以安全使用,由于方法同步,StringBuffer
在单线程环境下的性能略低于StringBuilder
,但在多线程环境下性能更稳定。
总的来说, String
适用于字符串不经常修改且在多线程环境下使用的场景,StringBuilder 适用于字符串经常修改且在单线程环境下使用的场景,StringBuffer 适用于字符串经常修改且在多线程环境下使用的场景。
例如,在单线程环境下进行大量字符串拼接操作时,使用StringBuilder
可以获得更好的性能;而在多线程环境下进行字符串操作时,使用StringBuffer
可以保证线程安全。
2. 你用过哪些集合?
-
用过ArrayList,它是基于动态数组实现的列表,支持快速随机访问,适用于需要快速随机访问元素的场景。
-
用过 HashSet,基于哈希表实现的集合,不允许重复元素,适用于需要快速查找且不允许重复元素的场景。
-
用过HashMap,基于哈希表实现的映射,适用于需要快速查,不是线程安全的
-
用过Hashtable,也是基于哈希表实现的映射,不允许使用
null
键和null
值,线程安全。 -
用过TreeMap,基于红黑树实现的映射,键按升序排列,适用于需要键按特定顺序排列的场景。
3. HashMap和TreeMap有哪些区别?
-
数据结构:HashMap是基于哈希表实现的,通过键的哈希值来存储数据,因此它具有较快的查找速度。而TreeMap则是基于红黑树实现的,数据按照键的自然顺序或自定义顺序进行排序,因此它具有有序性。
-
键的要求:HashMap的键不能是null,因为null值无法计算哈希值。而TreeMap的键可以是null,但只有一个null键,因为TreeMap需要键来进行排序。
-
线程安全性:HashMap是非线程安全的,如果多个线程同时修改HashMap,可能会导致数据不一致。而TreeMap也是非线程安全的,原因与HashMap相同。
-
性能:在插入、删除和查找操作中,HashMap通常具有更好的性能,因为它可以通过哈希值直接定位到数据所在的位置。而TreeMap由于需要维护数据的顺序,因此在插入和删除操作时可能需要更多的时间。
-
适用场景:HashMap适用于需要快速查找、插入和删除数据的场景,特别是当键不需要排序时。而TreeMap适用于需要按键排序的场景,例如范围查找、中序遍历等。
4. Java里的反射机制简单说下
Java中的反射机制允许程序在运行时动态地获取类的信息,并且能够操作类的字段、方法和构造函数。简单来说,反射就是提供在运行时获取类信息以及动态调用类的方法的能力。
例子:
public class ReflectionDemo {
public static void main(String[] args) throws Exception {
// 1. 动态加载类
Class<?> clazz = Class.forName("com.example.User");
// 2. 创建对象(无参构造)
Object obj = clazz.getDeclaredConstructor().newInstance();
// 3. 修改私有字段
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true); // 允许访问私有字段
nameField.set(obj, "Alice");
// 4. 调用私有方法
Method greetMethod = clazz.getDeclaredMethod("greet");
greetMethod.setAccessible(true);
String result = (String) greetMethod.invoke(obj); // 输出 "Hello, Alice"
System.out.println(result);
}
}
class User {
private String name;
private String greet() {
return"Hello, " + name;
}
}
反射的几个特点:
-
动态性:反射允许程序在运行时而不是编译时确定类的结构和行为。
-
访问控制:即使是私有的成员(字段、方法或构造函数),也可以通过反射被访问和修改(尽管这样做通常不推荐,因为它破坏了封装性)。
-
类型检查的灵活性:反射可以在运行时检查对象的类型,并执行相应的操作,而不需要在编译时知道具体的类型。
-
类加载:反射可以动态地加载类,这意味着可以在程序运行过程中加载新的类或接口。
不