String类
String是Java开发中非常高频使用的一个类
重要
它有两个子类,StringBuffer 和 StringBuilder 在项目中也会被高频使用
classDiagram
class String {
-final char[] value
+length() int
+charAt(int) char
+substring(int) String
+equals(Object) boolean
}
class StringBuilder {
+append(String) StringBuilder
+toString() String
}
class StringBuffer {
+append(String) StringBuffer
+toString() String
}
String <.. StringBuilder
String <.. StringBuffer
对比
特点 | String | StringBuilder | StringBuffer |
---|---|---|---|
可变性 | 不可变 | 可变 | 可变 |
线程安全 | 是 | 否 | 是 |
性能 | 较差 | 最好 | 较好 |
适用场景 | 少量字符串操作 | 单线程大量字符串操作 | 多线程大量字符串操作 |
内存使用 | 每次修改都创建新对象 | 动态扩容,内存效率高 | 动态扩容,内存效率高 |
同步机制 | 不需要 | 不需要 | 需要 |
初始容量 | 无 | 16 | 16 |
扩容策略 | 不适用 | 2倍+2 | 2倍+2 |
示例代码
public class StringDemo {
public static void main(String[] args) {
// 字符串创建
String s1 = "hello"; // 字符串常量池
String s2 = new String("hello"); // 堆中新对象
String s3 = "hello";
// == 和 equals比较
System.out.println("s1 == s2: " + (s1 == s2)); // false
System.out.println("s1 == s3: " + (s1 == s3)); // true
System.out.println("s1 equals s2: " + s1.equals(s2)); // true
// 常用方法
System.out.println("长度: " + s1.length());
System.out.println("拼接: " + s1.concat(" world"));
System.out.println("子串: " + "hello".substring(1, 3)); // el
System.out.println("替换: " + "hello".replace('l', 'L')); // heLLo
System.out.println("分割: " + Arrays.toString("a,b,c".split(",")));
// 字符串拼接性能
long start = System.currentTimeMillis();
String result = "";
for(int i = 0; i < 10000; i++) {
result += i; // 性能差,每次创建新对象
}
long end = System.currentTimeMillis();
System.out.println("普通拼接耗时: " + (end - start) + "ms");
// 使用StringBuilder优化
start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for(int i = 0; i < 10000; i++) {
sb.append(i);
}
end = System.currentTimeMillis();
System.out.println("StringBuilder耗时: " + (end - start) + "ms");
// 其他常用方法
System.out.println("是否包含: " + "hello".contains("ell")); // true
System.out.println("去除空格: " + " hello ".trim()); // hello
System.out.println("格式化: " + String.format("姓名:%s, 年龄:%d", "张三", 25));
}
}
public class StringBufferDemo {
public static void main(String[] args) {
// 创建StringBuffer对象
StringBuffer sb = new StringBuffer();
// 追加字符串
sb.append("Hello");
sb.append(" ");
sb.append("World");
System.out.println("追加后: " + sb.toString());
// 插入字符串
sb.insert(5, " Java");
System.out.println("插入后: " + sb.toString());
// 删除字符串
sb.delete(5, 10);
System.out.println("删除后: " + sb.toString());
// 替换字符串
sb.replace(0, 5, "Hi");
System.out.println("替换后: " + sb.toString());
// 反转字符串
sb.reverse();
System.out.println("反转后: " + sb.toString());
// 设置长度
sb.setLength(5);
System.out.println("设置长度后: " + sb.toString());
// 获取容量
System.out.println("当前容量: " + sb.capacity());
// 确保容量
sb.ensureCapacity(50);
System.out.println("确保容量后: " + sb.capacity());
}
}
public class StringBuilderDemo {
public static void main(String[] args) {
// 创建StringBuilder对象
StringBuilder sb = new StringBuilder();
// 追加字符串
sb.append("Hello");
sb.append(" ");
sb.append("World");
System.out.println("追加后: " + sb.toString());
// 插入字符串
sb.insert(5, " Java");
System.out.println("插入后: " + sb.toString());
// 删除字符串
sb.delete(5, 10);
System.out.println("删除后: " + sb.toString());
// 替换字符串
sb.replace(0, 5, "Hi");
System.out.println("替换后: " + sb.toString());
// 反转字符串
sb.reverse();
System.out.println("反转后: " + sb.toString());
// 设置长度
sb.setLength(5);
System.out.println("设置长度后: " + sb.toString());
// 获取容量
System.out.println("当前容量: " + sb.capacity());
// 确保容量
sb.ensureCapacity(50);
System.out.println("确保容量后: " + sb.capacity());
// 链式调用
StringBuilder chain = new StringBuilder()
.append("Hello")
.append(" ")
.append("World")
.insert(5, " Java")
.delete(5, 10)
.replace(0, 5, "Hi");
System.out.println("链式调用结果: " + chain.toString());
}
}
使用场景
String使用场景
-
字符串常量定义
String name = "张三"; String path = "/api/v1/users";
-
字符串比较和查找
if (userName.equals("admin")) { // 处理管理员逻辑 }
-
字符串分割和截取
String[] parts = "a,b,c".split(","); String sub = "hello".substring(0, 2);
-
字符串格式化
String message = String.format("用户%s的年龄是%d", name, age);
StringBuilder使用场景
-
大量字符串拼接
StringBuilder sql = new StringBuilder(); sql.append("SELECT * FROM users WHERE 1=1"); if (name != null) { sql.append(" AND name = '").append(name).append("'"); }
-
动态构建HTML/XML
StringBuilder html = new StringBuilder(); html.append("<div>") .append("<h1>").append(title).append("</h1>") .append("<p>").append(content).append("</p>") .append("</div>");
-
日志信息构建
StringBuilder log = new StringBuilder(); log.append("用户登录失败:") .append("用户名=").append(username) .append(", IP=").append(ip) .append(", 时间=").append(new Date());
StringBuffer使用场景
-
多线程环境下的字符串操作
public class LogBuffer { private StringBuffer buffer = new StringBuffer(); public synchronized void appendLog(String message) { buffer.append(new Date()).append(": ").append(message).append("\n"); } }
-
线程安全的字符串构建器
public class ThreadSafeBuilder { private StringBuffer buffer = new StringBuffer(); public void buildMessage(String part) { buffer.append(part); } public String getResult() { return buffer.toString(); } }
-
并发环境下的日志记录
public class ConcurrentLogger { private StringBuffer logBuffer = new StringBuffer(); public void log(String message) { synchronized(logBuffer) { logBuffer.append(Thread.currentThread().getName()) .append(": ") .append(message) .append("\n"); } } }
选择建议
- 如果字符串内容固定,使用String
- 如果单线程下需要频繁修改字符串,使用StringBuilder
- 如果多线程下需要频繁修改字符串,使用StringBuffer
- 如果字符串操作次数较少,直接使用String即可
- 如果字符串操作次数较多,优先考虑StringBuilder(单线程)或StringBuffer(多线程)