Java字符串操作的四種正確姿勢與常用模板
一 Java中常用方法
1. 基礎獲取類
s 表示某一個字符串String
| 方法 | 說明 | 競賽避坑指南 |
|---|---|---|
s.length() | 返回字符串長度 | 注意:它是方法,必須帶 ()。數(shù)組是 .length(屬性)。 |
s.charAt(i) | 獲取索引 i 處的字符 | 配合 while 循環(huán)做邊界檢查(i >= 0 && i < s.length())。 |
s.indexOf(str) | 查找子串第一次出現(xiàn)的位置 | 如果沒找到,返回 -1。在處理特定模式搜索時極好用。 |
s.substring(start, end) | 截取子串 | 重點:左閉右開 [start, end)。包含 start,但不包含 end。 |
2. 比較與判斷類
在競賽中,千萬不要用 == 比較字符串內(nèi)容!
• s.equals(s2):比較兩個字符串內(nèi)容是否完全相等。
• s.equalsIgnoreCase(s2):忽略大小寫比較(在某些天梯賽題目中很有用)。
• s.startsWith(prefix) / s.endsWith(suffix):判斷是否以某段開頭或結尾。
• s.isEmpty():判斷長度是否為 0。
3. 修改與轉換類(產(chǎn)生新字符串)
注意:Java 中的 String 是不可變的,這些方法都會返回一個全新的字符串。
• s.toLowerCase() / s.toUpperCase():全部轉小寫/大寫。
• s.trim():去掉首尾空格(處理輸入數(shù)據(jù)不規(guī)范時是救命藥)。
• s.replace(old, new):替換所有匹配的字符或子串。
• s.toCharArray():競賽神技。如果你覺得 s.charAt(i) 寫起來太長,先轉成 char[],然后用 arr[i] 訪問,速度更快且代碼更短。
4. 分割與合并
s.split(String regex):按規(guī)則切分。
例: String[] words = s.split(" "); 可以把句子拆成單詞。
String.join(delimiter, elements):把數(shù)組或列表用指定符號連起來。
5.StringBuilder
如果在循環(huán)里頻繁修改字符串(比如 s += “a”),Java 每次都會創(chuàng)建新對象,導致 超時,所以我們可以選擇來new上一個StringBuilder
為什么我們要使用StringBuilder呢?因為在Java中,String是不可變的,比如當我們有一個字符串 s = “a” 時,執(zhí)行"s = s + "b"時:
1.Java不會在原來的"a"的后面直接加"b";
2.而是創(chuàng)建一個新對象,把"a"拷貝過去,再把"b"加上去;
3.導致原來的"a"變成了多余的那個,占用了內(nèi)存
所以當我們在循環(huán)10000做" s += “a” " ,則會創(chuàng)建10000個臨時字符串對象,直接讓內(nèi)存爆炸??,同時時間復雜度也到達了O(N ^ 2).
而StringBuilder的優(yōu)勢是他內(nèi)部有著一個字符數(shù)組(char[]),當我們執(zhí)行sb.append時,它直接在數(shù)組的下一個空位填入‘b',不創(chuàng)建新對象,如果數(shù)組滿了,它會自動擴大一倍(擴容),然后繼續(xù)填,時間復雜度接近 O(N).
競賽常用方法:
| 方法 | 說明 | 競賽場景 |
|---|---|---|
sb.append(xxx) | 追加內(nèi)容 | 拼接答案、拼接數(shù)字、拼接字符。支持鏈式調(diào)用。 |
sb.reverse() | 原地翻轉 | 判斷回文、大數(shù)加法(低位對齊)、反轉字符串。 |
sb.delete(start, end) | 刪除一段 | 類似于 substring 的逆操作,清理不需要的后綴。 |
sb.setCharAt(i, c) | 修改指定字符 | 這是 String 做不到的!修改某個位置的字符。 |
sb.insert(offset, str) | 在指定位置插入 | 比如在最前面插入一個負號。 |
sb.length() | 獲取當前長度 | 循環(huán)遍歷時用。 |
sb.toString() | 轉回 String | 最終輸出答案時必須調(diào)用。 |
sb.setLength(0) | 清空 StringBuilder | 把指針重置為 0,內(nèi)容邏輯上清空了 |
現(xiàn)在有一個新場景,假設我們要處理 N N N 組數(shù)據(jù),每組數(shù)據(jù)都要拼一個結果并輸出。
A方法:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 3; i++) {
sb.append("Data" + i);
System.out.println(sb.toString());
}
這種情況下
第一輪:Data0
第二輪:Data0Data1 <-- 錯了!上一輪的臟數(shù)據(jù)還在!
第三輪:Data0Data1Data2
數(shù)據(jù)亂了,并不是我們想要的結果
B方法:直接new
for (int i = 0; i < 100000; i++) {
StringBuilder sb = new StringBuilder();
sb.append("Data" + i);
System.out.println(sb.toString());
// 循環(huán)結束,sb 變成垃圾
}
這種情況下,成功輸出我們想要的結果
后果:
內(nèi)存直接爆炸,你在內(nèi)存里創(chuàng)建了 10 萬個對象,又丟棄了 10 萬個,同時每次 new 出來的數(shù)組都很小,每次都要重新經(jīng)歷從小變大的擴容過程。
C方法:使用setLength(0)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
sb.setLength(0);
sb.append("Data" + i);
System.out.println(sb.toString());
}
這種情況下,成功輸出我們想要的結果
后果:
全程只有 1 個對象,同時 比如第一輪你的字符串很長,把數(shù)組撐到了 5000 大小。第二輪開始時,sb 依然擁有 5000 的容量,根本不需要再擴容,直接填進去就行
二 . 四種字符串必會技能
1.字符串與數(shù)字的切換
場景:題目給了“1000”,要求變成數(shù)字1000去做加減乘除,或者是算出結果250后將其拼接到字符串
A.String 轉 int / long
Integer.parseInt(s);
String s = "12345";
int num = Integer.parseInt(s); // 轉 int
long bigNum = Long.parseLong("9999999999"); // 轉 long (超過21億必須用這個)
int 最大只能存約 21 億 ( 2 × 10 9 2 \times 10^9 2×109)。
如果題目說數(shù)字可能很大(比如 18 位),必須用 Long.parseLong。
如果字符串里混進了空格或字母(比如 " 123" 或 “12a”),這行代碼會直接報錯
NumberFormatException。
如果只是首尾空格,直接用s.trim()就好
但如果是“123ad 23;”等這些混入了各種非數(shù)字的字符時,則需要使用其他方法
第一種方法:暴力清洗,直接把所有非數(shù)字的去掉
String s = "123ad 23;";
String clean = s.replaceAll("[^0-9]", "");
// [^0-9] == \\D
意思是:除了 0-9 以外的所有字符,把所有非數(shù)字字符替換成空字符串
int num = Integer.parseInt(clean);
System.out.println(num);
//結果為:12323
如果要求讀取直到遇到非數(shù)字就輸出,那么就不能使用上面的方法
第二種方法:精細提取法(讀取直到遇到非數(shù)字)
String s = "123ad 23;";
int num = 0;
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
// 如果是數(shù)字,就累加
if (Character.isDigit(ch)) {
// 核心公式:原數(shù)字 * 10 + 新的一位
// c - '0' 是把字符變成數(shù)字
num = num * 10 + (ch - '0');
} else {
break;
}
}
System.out.println(num);
//結果為:123
B. int/long 轉 String
這是為了輸出或者拼接
int num = 42; // 寫法 1 :利用 Java 的自動裝箱,雖然不是最快但最不容易錯 String s1 = num + ""; // 寫法 2 :性能稍好,看著專業(yè) String s2 = String.valueOf(num);
2.字符與ASCII 碼
場景: “把所有字母向后移 3 位”,或者“判斷這個字符是不是數(shù)字”
核心原理: char 在 Java 里本質上是一個整數(shù),要把 char 當成整數(shù)去用
‘0’ 的整數(shù)值是 48。
‘A’ 的整數(shù)值是 65。
‘a’ 的整數(shù)值是 97。
A.字符轉數(shù)字
問題:怎么把字符 ‘5’ 變成整數(shù) 5?
int num = (int)'5'; //錯誤 //輸出:53 并非 5
int num = '5' - '0'; //正確 // 53 - 48 = 5
B. 字母移位
char c = 'A'; // 往后移 1 位變成 'B' char next = (char)(c + 1); // 必須強轉回 char,因為計算結果是 int
C.字符的大小寫轉換
//'A' = 65, 'a' = 97
//小寫變大寫 減32
char uppercaseLetters = (char)('a' - 32);
//大寫變小寫 加32
char lowercaseLetters = (char)('B' + 32);
D. 判斷字符類型
用 Java 自帶的工具類 Character
Character.isDigit( c ) : 是不是 ‘0’-‘9’?
Character.isLetter( c ): 是不是字符?
Character.isLetterOrDigit( c ): 是不是字符或者數(shù)字?
Character.isUpperCase( c ): 是不是大寫?
Character.isLowerCase( c ): 是不是小寫?
3.格式化輸出
題目出現(xiàn)要“保留小數(shù)”和“補零”的情況下:
double pi = 3.1415926;
int hour = 5;
// 1. 保留 2 位小數(shù) (會自動四舍五入)
System.out.printf("%.2f", pi);
// 輸出: 3.14
// 2. 整數(shù)補零 (總共占 2 位,不夠補 0)
System.out.printf("%02d", hour);
// 輸出: 05
// 3. 組合拳:輸出 "Time: 05, Score: 3.14"
String res = String.format("Time: %02d, Score: %.2f", hour, pi);
System.out.println(res);
4. 字典序比較 (排序用的)
題目出現(xiàn)要“請把這些名字按字典序從小到大排列”, 不能用 < 或 > 比較字符串,要用 compareTo()
String s1 = "apple";
String s2 = "banana";
// 返回值規(guī)則:
// < 0 : s1 在 s2 前面 (apple < banana)
// == 0 : 相等
// > 0 : s1 在 s2 后面
int result = s1.compareTo(s2);
// 對字符串數(shù)組排序
String[] arr = {"dog", "cat", "apple"};
Arrays.sort(arr); // 默認就是按字典序排的:apple, cat, dog
5. 正則表達式分割
題目給出:“Please, split this… sentence!” (標點混雜空格),用普通的 split(" ") 切不干凈,所以給用下面的方法
String s = "Hello, World! Java";
// split 里面填的是正則表達式
// [ ,!]+ 表示:只要遇到 空格、逗號、感嘆號 中的任意一個或多個,就切一刀
String[] parts = s.split("[ ,!]+");
總結
到此這篇關于Java字符串操作的四種正確姿勢與常用模板的文章就介紹到這了,更多相關Java字符串操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
不喜歡羅里吧嗦,講的很精簡易懂。從基礎開始講,后續(xù)會講到JAVA高級,中間會穿插面試題和項目實戰(zhàn),希望能給大家?guī)韼椭?/div> 2022-03-03
如何動態(tài)改變Retrofit的base url和rest版本詳解
這篇文章主要給大家介紹了關于如何動態(tài)改變Retrofit的base url和rest版本的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2018-09-09
Java中的ThreadLocal與ThreadLocalMap詳解
這篇文章主要介紹了Java中的ThreadLocal與ThreadLocalMap詳解,ThreadLocal 是一個線程局部變量,其實的功用非常簡單,就是為每一個使用該變量的線程都提供一個變量值的副本,是Java中一種較為特殊的線程綁定機制,需要的朋友可以參考下2023-09-09最新評論

