Java從入門到“放棄”(精通)之旅🚀——String類⑩
前言
在Java編程中,String類是最常用也是最重要的類之一。無論是日常開發還是面試,對String類的深入理解都是必不可少的。
1. String類的重要性
在C語言中,字符串只能使用字符數組或字符指針表示,操作字符串需要依賴標準庫函數。這種方式將數據和操作分離,不符合面向對象思想。Java專門提供了String類來解決這個問題。
String類在開發中無處不在,例如:
- 字符串轉數字
- 字符串拼接
- 數據校驗等
面試中也經常被問到String相關的問題,如String、StringBuffer和StringBuilder的區別等。
2. 常用方法
2.1 字符串構造
String類提供了多種構造方式,常用的有三種:
public static void main(String[] args) {// 使用常量串構造String s1 = "hello bit";System.out.println(s1);// 直接new String對象String s2 = new String("hello bit");System.out.println(s2);// 使用字符數組進行構造char[] array = {'h','e','l','l','o',' ','b','i','t'};String s3 = new String(array);System.out.println(s3);
}
注意:String是引用類型,并不是直接保存字符串內容,而是內部通過字符數組存儲字符串內容。
代碼示例:
public static void main(String[] args) {// s1和s2引用的是不同對象 s1和s3引用的是同一對象String s1 = new String("hello");String s2 = new String("world");String s3 = s1;System.out.println(s1.length()); // 獲取字符串長度---輸出5System.out.println(s1.isEmpty()); // 如果字符串長度為0,返回true,否則返回false
}
2.2 String對象的比較
Java提供了4種字符串比較方式:
- ==比較引用地址
public static void main(String[] args) {String s1 = new String("hello");String s2 = new String("hello");String s3 = new String("world");String s4 = s1;System.out.println(s1 == s2); // falseSystem.out.println(s2 == s3); // falseSystem.out.println(s1 == s4); // true
}
- equals()方法:按字典序比較
public static void main(String[] args) {String s1 = new String("hello");String s2 = new String("hello");String s3 = new String("Hello");System.out.println(s1.equals(s2)); // trueSystem.out.println(s1.equals(s3)); // false
}
- compareTo()方法:按字典序比較并返回差值
public static void main(String[] args) {String s1 = new String("abc");String s2 = new String("ac");String s3 = new String("abc");String s4 = new String("abcdef");System.out.println(s1.compareTo(s2)); // -1System.out.println(s1.compareTo(s3)); // 0System.out.println(s1.compareTo(s4)); // -3
}
- compareToIgnoreCase()方法:忽略大小寫的compareTo
public static void main(String[] args) {String s1 = new String("abc");String s2 = new String("ac");String s3 = new String("ABC");String s4 = new String("abcdef");System.out.println(s1.compareToIgnoreCase(s2)); // -1System.out.println(s1.compareToIgnoreCase(s3)); // 0System.out.println(s1.compareToIgnoreCase(s4)); // -3
}
2.3 字符串查找
常用查找方法:
方法 | 功能 |
---|---|
char charAt(int index) | 返回index位置上字符,如果index為負數或者越界,拋出IndexOutOfBoundsException 異常 |
int indexOf(int ch) | 返回ch第一次出現的位置,沒有返回-1 |
int indexOf(int ch, int fromIndex) | 從fromIndex位置開始找ch第一次出現的位置,沒有返回-1 |
int indexOf(String str) | 返回str第一次出現的位置,沒有返回-1 |
int indexOf(String str, int fromIndex) | 從fromIndex位置開始找str第一次出現的位置,沒有返回-1 |
int lastIndexOf(int ch) | 從后往前找,返回ch第一次出現的位置,沒有返回-1 |
int lastIndexOf(int ch, int fromIndex) | 從fromIndex位置開始找,從后往前找ch第一次出現的位置,沒有返回-1 |
int lastIndexOf(String str) | 從后往前找,返回str第一次出現的位置,沒有返回-1 |
int lastIndexOf(String str, int fromIndex) | 從fromIndex位置開始找,從后往前找str第一次出現的位置,沒有返回-1 |
public static void main(String[] args) {String s = "aaabbbcccaaabbbccc";System.out.println(s.charAt(3)); // 'b'System.out.println(s.indexOf('c')); // 6System.out.println(s.lastIndexOf('c')); // 17
}
2.4 字符串轉化
- 數值和字符串互轉
public static void main(String[] args) {// 數字轉字符串String s1 = String.valueOf(1234);String s2 = String.valueOf(12.34);// 字符串轉數字int data1 = Integer.parseInt("1234");double data2 = Double.parseDouble("12.34");
}
- 大小寫轉換
public static void main(String[] args) {String s1 = "hello";String s2 = "HELLO";System.out.println(s1.toUpperCase()); // HELLOSystem.out.println(s2.toLowerCase()); // hello
}
- 字符串與數組互轉
public static void main(String[] args) {String s = "hello";// 字符串轉數組char[] ch = s.toCharArray();// 數組轉字符串String s2 = new String(ch);
}
2.5 字符串替換
public static void main(String[] args) {String str = "helloworld";System.out.println(str.replaceAll("l", "_")); // he__owor_dSystem.out.println(str.replaceFirst("l", "_")); // he_loworld
}
注意:字符串是不可變對象,替換操作會創建新對象。
2.6 字符串拆分
public static void main(String[] args) {// 基本拆分String str = "hello world hello bit";String[] result = str.split(" ");// 部分拆分String[] result2 = str.split(" ", 2);// 拆分IP地址String ip = "192.168.1.1";String[] ipParts = ip.split("\\.");
}
2.7 字符串截取
public static void main(String[] args) {String str = "helloworld";System.out.println(str.substring(5)); // worldSystem.out.println(str.substring(0, 5)); // hello
}
2.8 其他操作方法
public static void main(String[] args) {// 去除首尾空格String str = " hello world ";System.out.println(str.trim());// 大小寫轉換String mixed = "Hello%$$%@#$%World";System.out.println(mixed.toUpperCase());System.out.println(mixed.toLowerCase());
}
3. 字符串的不可變性
String類被設計為不可變類,主要原因有:
- 方便實現字符串常量池
- 線程安全
- 便于緩存hash code
注意:String不可變不是因為final修飾,而是因為其設計如此。
public final class String {private final char value[];// ...
}
4. 字符串修改
由于String不可變,頻繁修改會產生大量臨時對象,效率低下:
public static void main(String[] args) {// 不推薦的寫法String s = "";for(int i = 0; i < 10000; ++i){s += i;}// 推薦使用StringBuilderStringBuilder sb = new StringBuilder();for(int i = 0; i < 10000; ++i){sb.append(i);}
}
5. StringBuilder和StringBuffer
5.1 StringBuilder介紹
StringBuilder是可變的字符串類,方法表:
方法 | 說明 |
---|---|
StringBuffer append(String str) | 在尾部追加,相當于String的+=,可以追加:boolean、char、char[]、double、float、int、long、Object、String、StringBuffer的變量 |
char charAt(int index) | 獲取index位置的字符 |
int length() | 獲取字符串的長度 |
int capacity() | 獲取底層保存字符串空間總的大小 |
void ensureCapacity(int minimumCapacity) | 擴容 |
void setCharAt(int index, char ch) | 將index位置的字符設置為ch |
int indexOf(String str) | 返回str第一次出現的位置 |
int indexOf(String str, int fromIndex) | 從fromIndex位置開始查找str第一次出現的位置 |
int lastIndexOf(String str) | 返回最后一次出現str的位置 |
int lastIndexOf(String str, int fromIndex) | 從fromIndex位置開始找str最后一次出現的位置 |
StringBuffer insert(int offset, String str) | 在offset位置插入:八種基類類型 & String類型 & Object類型數據 |
StringBuffer deleteCharAt(int index) | 刪除index位置字符 |
StringBuffer delete(int start, int end) | 刪除[start, end)區間內的字符 |
StringBuffer replace(int start, int end, String str) | 將[start, end)位置的字符替換為str |
String substring(int start) | 從start開始一直到末尾的字符以String的方式返回 |
String substring(int start, int end) | 將[start, end)范圍內的字符以String的方式返回 |
StringBuffer reverse() | 反轉字符串 |
String toString() | 將所有字符按照String的方式返回 |
常用方法部分代碼示例:
public static void main(String[] args) {StringBuilder sb = new StringBuilder("hello");sb.append(" world"); // 追加sb.insert(5, ","); // 插入sb.delete(5, 6); // 刪除sb.reverse(); // 反轉String result = sb.toString(); // 轉為String
}
5.2 面試題
-
String、StringBuffer、StringBuilder的區別
- String不可變,后兩者可變
- StringBuffer線程安全,StringBuilder非線程安全
- StringBuilder性能更高
-
創建了多少個String對象
String str = new String("ab"); // 2個(常量池1個,堆1個)
String str = new String("a") + new String("b"); // 6個
6. String類OJ題解
6.1 第一個只出現一次的字符
class Solution {public int firstUniqChar(String s) {int[] count = new int[256];for(int i = 0; i < s.length(); ++i){count[s.charAt(i)]++;}for(int i = 0; i < s.length(); ++i){if(1 == count[s.charAt(i)]){return i;}}return -1;}
}
6.2 最后一個單詞的長度
import java.util.Scanner;public class Main {public static void main(String[] args){Scanner sc = new Scanner(System.in);while(sc.hasNext()){String s = sc.nextLine();int len = s.substring(s.lastIndexOf(" ")+1).length();System.out.println(len);}sc.close();}
}
6.3 檢測字符串是否為回文
class Solution {public static boolean isValidChar(char ch){return (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9');}public boolean isPalindrome(String s) {s = s.toLowerCase();int left = 0, right = s.length()-1;while(left < right){while(left < right && !isValidChar(s.charAt(left))) left++;while(left < right && !isValidChar(s.charAt(right))) right--;if(s.charAt(left) != s.charAt(right)) return false;left++;right--;}return true;}
}
總結
String類是Java中最重要的類之一,理解其不可變特性、掌握常用方法以及了解StringBuilder/StringBuffer的區別,對于編寫高效Java程序至關重要。希望本文能幫助大家全面掌握String類的使用!
JavaSE往期專欄
- Java從入門到“放棄”(精通)之旅——啟航①
- Java從入門到“放棄”(精通)之旅——數據類型與變量②
- Java從入門到“放棄”(精通)之旅——運算符③
- Java從入門到“放棄”(精通)之旅——程序邏輯控制④
- Java從入門到“放棄”(精通)之旅——方法的使用⑤
- Java從入門到“放棄”(精通)之旅——數組的定義與使用⑥
- Java從入門到“放棄”(精通)之旅——類和對象全面解析⑦
- Java從入門到“放棄”(精通)之旅——繼承與多態⑧
- Java從入門到“放棄”(精通)之旅——抽象類和接口⑨