字符串處理是 Java 日常開發最高頻操作。本文系統梳理三大字符串類特性、性能差異、線程安全性,並深度講解格式化輸出的多種方案。
| 特性 | String | StringBuilder | StringBuffer |
|---|---|---|---|
| 可變性 | 不可變 | 可變 | 可變 |
| 線程安全 | 天然安全(不可變) | 非線程安全 | 同步方法,線程安全 |
| 性能 | 拼接產生大量臨時對象 | 單線程最高 | 同步開銷,略低 |
| 適用場景 | 少量拼接、常量、鍵值 | 單線程大量拼接 | 多線程共享拼接 |
| JDK 版本 | 1.0 | 5.0 | 1.0 |
String s = "a" + 2 + "b" + 2.2;
// 編譯器優化為:
String s = new StringBuilder()
.append("a").append(2).append("b").append(2.2)
.toString();
// 產生 1 個 StringBuilder + 1 個 String,而非 4 個 String
但循環中拼接仍會產生大量對象:
// 反例:循環中用 +
String s = "";
for (int i = 0; i < 10000; i++) s += i; // 10000 個 StringBuilder + 10000 個 String
// 正例:循環外複用 StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) sb.append(i);
String s = sb.toString();
length()、isEmpty()charAt(index)、toCharArray()、getBytes()equals()、equalsIgnoreCase()、compareTo()、compareToIgnoreCase()indexOf()、lastIndexOf()、contains()、startsWith()、endsWith()substring(begin, end)toUpperCase()、toLowerCase()、trim()、replace()、replaceAll(regex)split(regex) → 返回 String[]String.valueOf(obj)、String.format()注意:split 參數是正則表達式,"a.b".split(".") 會按任意字符分割,需用 split("\\.")。
System.out.format("%-3d %-5.3f%n", 1, 2.235235); // 左對齊寬度3、浮點保留3位
System.out.printf("%-3d %-5.3f%n", 1, 2.235235); // 同樣效果
// 輸出到控制台
Formatter f = new Formatter(System.out);
f.format("%-3d %-8.2f %-10s%n", 1, 2.235, "touch");
// 輸出到文件
try (Formatter ff = new Formatter(new FileOutputStream("format.txt"))) {
ff.format("%-3d %-8.2f %-10s%n", 1, 2.235, "touch");
}
// 輸出到字符串
StringBuilder sb = new StringBuilder();
Formatter f3 = new Formatter(sb);
f3.format("(%d %.2f %s)", 1, 2.235, "touch");
String result = sb.toString(); // "(1 2.24 touch)"
String s = String.format("(%d %.2f %s)", 1, 2.235, "touch");
// 返回格式化字符串,不直接輸出
| 佔位符 | 含義 | 示例 |
|---|---|---|
| %d | 十進制整數 | %05d → 00042 |
| %f | 浮點數 | %.2f → 3.14 |
| %s | 字符串 | %-10s → 左對齊寬度10 |
| %x/%X | 十六進制 | %02x → 2a |
| %c | 字符 | %c → 'A' |
| %b | 布爾值 | %b → true |
| %n | 平台換行符 | 跨平台換行 |
寬度/精度語法:%[flags][width][.precision]conversion
-左對齊、0補零、+顯示符號、 正數前空格
public class HexUtil {
public static String format(byte[] data) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.length; i++) {
if (i % 16 == 0) {
sb.append(String.format("%05x: ", i));
}
sb.append(String.format("%02x ", data[i]));
if (i % 16 == 15) sb.append('\n');
}
return sb.toString();
}
}