字串處理是業務開發高頻需求。本文整理實戰中常用的字串替換、多模式分割、全半角轉換工具方法,提供生產級代碼實作與設計考量。
/**
* 字串替換:將 source 中所有 beRepStr 替換為 repStr
* @param source 原字串
* @param beRepStr 被替換子串
* @param repStr 替換目標串
* @return 替換後字串
*/
public static String replaceStr(String source, String beRepStr, String repStr) {
if (source == null || beRepStr == null || beRepStr.isEmpty()) {
return source;
}
int index = source.indexOf(beRepStr);
if (index < 0) {
return source;
}
StringBuilder sb = new StringBuilder();
int lastEnd = 0;
while (index >= 0) {
sb.append(source, lastEnd, index);
sb.append(repStr);
lastEnd = index + beRepStr.length();
index = source.indexOf(beRepStr, lastEnd);
}
sb.append(source, lastEnd, source.length());
return sb.toString();
}
indexOf(str, fromIndex) 避免重複掃描生產建議:實際專案優先使用 String.replace(CharSequence, CharSequence)(Java 5+)或 Apache Commons Lang StringUtils.replace(),經過高度優化且處理邊界情況完善。
/**
* 智慧分割:自動檢測分隔符(空白鍵 或 #)
* @param test 待分割字串
* @param sep 預設分隔符
* @return 分割後陣列
*/
public static String[] getFields(String test, String sep) {
if (test == null) return new String[0];
// 智慧檢測分隔符邏輯
int spaceIdx = test.indexOf(' ');
int hashIdx = test.indexOf('#');
if (spaceIdx != -1) {
if (hashIdx != -1 && spaceIdx > hashIdx) {
sep = "#"; // # 出現較早,優先作為分隔符
}
} else {
sep = "#"; // 無空白則用 #
}
if (" ".equals(sep)) {
// 空白分割:連續空白視為單一分隔,去除首尾空白
return test.trim().split("\\s+");
} else {
// # 分割:保留空欄位行為由 split 決定
return test.trim().split("#");
}
}
trim() 移除首尾干擾字元\\s+ 正則處理連續空白、Tab 等
public static String toFullWidth(String input) {
if (input == null) return null;
char[] chars = input.toCharArray();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (c == ' ') { // 半角空白
chars[i] = '\u3000';
} else if (c >= '\u0021' && c <= '\u007E') { // 可見半角字元
chars[i] = (char) (c + 0xFEE0);
}
}
return new String(chars);
}
public static String toHalfWidth(String input) {
if (input == null) return null;
char[] chars = input.toCharArray();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (c == '\u3000') { // 全角空白
chars[i] = ' ';
} else if (c >= '\uFF01' && c <= '\uFF5E') { // 可見全角字元
chars[i] = (char) (c - 0xFEE0);
}
}
return new String(chars);
}
| 原代碼問題 | 改進方案 |
|---|---|
逐字 getBytes("unicode") 極慢 | 直接 char 陣列運算,零物件分配 |
| 依賴特定位元組位置 (b[2], b[3]) 不可移植 | 基於 Unicode 碼位標準,跨平台一致 |
字串連接 outStr += ... 產生大量垃圾 | char 陣列就地修改,單次 new String |
| 未處理空白字元特殊映射 | 額外處理 U+3000 ↔ U+0020 |
public final class StringUtils {
private StringUtils() {} // 工具類禁止實例化
// 上述三個公開靜態方法...
public static void main(String[] args) {
// 全半角測試
String half = "#@$%^&*()";
String full = "#@$%^&*()";
System.out.println("半轉全: " + half + " → " + toFullWidth(half));
System.out.println("全轉半: " + full + " → " + toHalfWidth(full));
// 分割測試
String[] r1 = getFields("23#99#99#99", "#");
String[] r2 = getFields("a b c d", " ");
System.out.println("#分割: " + Arrays.toString(r1));
System.out.println("空白分割: " + Arrays.toString(r2));
// 替換測試
System.out.println("替換: " + replaceStr("a,b,c", ",", "|"));
}
}
字串處理看似基礎,實則藏著效能陷阱與邊界陷阱。掌握 StringBuilder、char[] 直接操作、Unicode 碼位運算等核心技術,能寫出高效、正確、可維護的工具代碼。實際專案中,優先考慮成熟庫(Guava, Commons Lang, Apache Text),僅在特殊業務邏輯下自行實作。