目錄
- 一、構造器方法
- 二、String與字節數組的轉換(編碼與解碼)
- 1、字符串 --> 字節數組:(編碼)
- 2、字節數組 --> 字符串:(解碼)
- 3、iso-8859-1的特殊用法
- 4、byte數組的數字表示
- 三、常用API
- 1、常用方法
- 2、查找
- 3、字符串截取
- 4、和字符/字符數組相關
- 5、開頭與結尾
- 6、替換
- 四、常見算法題
- 1、模擬一個trim方法,去除字符串兩端的空格
- 2、將一個字符串進行反轉。將字符串中指定部分進行反轉。比如“ab`cdef`g”反轉為”ab`fedc`g”
- 3、獲取一個字符串在另一個字符串中出現的次數。比如:獲取“ ab”在 “abkkcadkabkebfkabkskab” 中出現的次數
- 4、獲取兩個字符串中最大相同子串。比如:str1 = "abcwerthelloyuiodef“;str2 = "cvhellobnm"
- 五、StringBuffer和StringBuilder
- 1、StringBuffer與StringBuilder的理解
- 2、StringBuilder、StringBuffer的API
- 3、效率測試
一、構造器方法
public String()
:初始化新創建的 String對象,以使其表示空字符序列String(String original)
: 初始化一個新創建的String
對象,使其表示一個與參數相同的字符序列;換句話說,新創建的字符串是該參數字符串的副本public String(char[] value)
:通過當前參數中的字符數組來構造新的Stringpublic String(char[] value,int offset, int count)
:通過字符數組的一部分來構造新的String
舉例:
//字面量定義方式:字符串常量對象
String str = "hello";//構造器定義方式:無參構造
String str1 = new String();//構造器定義方式:創建"hello"字符串常量的副本
String str2 = new String("hello");//構造器定義方式:通過字符數組構造
char chars[] = {'a', 'b', 'c','d','e'};
String str3 = new String(chars); // abcde
String str4 = new String(chars,0,3); // abc
二、String與字節數組的轉換(編碼與解碼)
1、字符串 --> 字節數組:(編碼)
public byte[] getBytes()
:使用平臺的默認字符集將此 String 編碼為 byte 序列,并將結果存儲到一個新的 byte 數組中public byte[] getBytes(String charsetName)
:使用指定的字符集將此 String 編碼到 byte 序列,并將結果存儲到新的 byte 數組
2、字節數組 --> 字符串:(解碼)
String(byte[])
:通過使用平臺的默認字符集解碼指定的 byte 數組,構造一個新的 String- String(byte[],int offset,int length) :用指定的字節數組的一部分,即從數組起始位置offset開始取length個字節構造一個字符串對象
String(byte[], String charsetName )
或 new String(byte[], int, int,String charsetName ):解碼,按照指定的編碼方式進行解碼
舉例:
byte[] b_gbk = "中".getBytes("gbk");
byte[] b_utf8 = "中".getBytes("utf-8");
byte[] b_iso88591 = "中".getBytes("iso-8859-1");
- 將返回"中"這個漢字分別在gbk、utf-8、iso-8859-1編碼下的字節數組表示
- 此時b_gbk的長度為2,b_utf8的長度為3,b_iso88591的長度為1
- 與getBytes()方法相反,可以通過new String(byte[], charsetName)方法用指定的字符集來還原這個"中"字,如:
String s_gbk = new String(b_gbk, "gbk");
String s_utf8 = new String(b_utf8, "utf-8");
String s_iso88591 = new String(b_iso88591, "iso-8859-1");
- 打印出s_gbk、s_utf8、s_iso88591可以看到,s_gbk和s_utf8都是"中",而s_iso88591是一個亂碼
- 這是因為iso-8859-1的編碼表中,根本就沒有包含漢字
- 因此"中".getBytes(“iso-8859-1”)得到的是"?“的字節數組表示
- 再通過new String(b_iso88591, “iso-8858-1”)還原得到的是”?"
3、iso-8859-1的特殊用法
- 有時候,為了讓中文字符適應某些特殊要求(如http header要求其內容必須是iso-8859-1編碼)
- 可能會通過將中文字符按照字節方式來編碼的情況,如:
String s_iso88591 = new String("中".getBytes("utf-8"), "iso-8859-1");
- 得到的字符串s_iso88591實際上是三個在iso-8859-1中的字符,在將這些字符傳送到目的地后,再通過相反的方式,即:
String s_utf8 = new String(s_iso88591.getBytes("iso-8859-1"), "utf-8");
- 從而得到正確的中文漢字"中",這樣就既保證了遵守協議規定,也支持了中文
4、byte數組的數字表示
byte[] b = "中".getBytes("utf-8");
for(int i=0; i<b.length; i++) {System.out.println(b[i]);
}
輸出:
-28
-72
-83
- 因為"中"的utf-8編碼為三個字節,分別是E4 B8 AD
- 以E4為例,換成二進制即為:1110 0100
- 該二進制數將以補碼存儲在內存中,最高位被視為符號位
- 因此原碼是:1110 0100(補碼) -> 1001 1011(反碼) -> 1001 1100(原碼)
- 即-(16+8+4)=-28
三、常用API
1、常用方法
- boolean isEmpty():字符串是否為空
- int length():返回字符串的長度
- String concat(xx):拼接
- boolean equals(Object obj):比較字符串是否相等,區分大小寫
boolean equalsIgnoreCase(Object obj)
:比較字符串是否相等,不區分大小寫int compareTo(String other)
:比較字符串大小,區分大小寫,按照Unicode編碼值比較大小- int compareToIgnoreCase(String other):比較字符串大小,不區分大小寫
String toLowerCase()
:將字符串中大寫字母轉為小寫String toUpperCase()
:將字符串中小寫字母轉為大寫- String trim():去掉字符串前后空白符
- public String intern():結果在常量池中共享
@Test
public void test1(){String s1 = "hello";String s2 = "HellO";System.out.println(s1.equals(s2));System.out.println(s1.equalsIgnoreCase(s2));String s3 = "abcd";String s4 = "adef";System.out.println(s3.compareTo(s4));String s5 = "abcd";String s6 = "aBcd";System.out.println(s5.compareTo(s6));System.out.println(s5.compareToIgnoreCase(s6));String s7 = "張ab";String s8 = "李cd";System.out.println(s7.compareTo(s8));String s9 = " he llo ";System.out.println("****" + s9.trim() + "*****");
}
2、查找
- boolean contains(xx):是否包含xx
int indexOf(xx)
:從前往后找當前字符串中xx,即如果有返回第一次出現的下標,要是沒有返回-1int indexOf(String str, int fromIndex)
:返回指定子字符串在此字符串中第一次出現處的索引,從指定的索引開始int lastIndexOf(xx)
:從后往前找當前字符串中xx,即如果有返回最后一次出現的下標,要是沒有返回-1int lastIndexOf(String str, int fromIndex)
:返回指定子字符串在此字符串中最后一次出現處的索引,從指定的索引開始反向搜索
@Test
public void test2(){String s1 = "教育尚硅谷教育";System.out.println(s1.contains("硅谷")); // trueSystem.out.println(s1.indexOf("教育")); // 0System.out.println(s1.indexOf("教育",1)); // 5System.out.println(s1.lastIndexOf("教育")); // 5System.out.println(s1.lastIndexOf("教育",4)); // 0
}
3、字符串截取
String substring(int beginIndex)
:返回一個新的字符串,它是此字符串的從beginIndex開始截取到最后的一個子字符串String substring(int beginIndex, int endIndex)
:返回一個新字符串,它是此字符串從beginIndex開始截取到endIndex(不包含)的一個子字符串
@Test
public void test3(){String s1 = "教育尚硅谷教育";System.out.println(s1.substring(2)); // 尚硅谷教育System.out.println(s1.substring(2,5));//[2,5) // 尚硅谷
}
4、和字符/字符數組相關
char charAt(index)
:返回[index]位置的字符char[] toCharArray()
: 將此字符串轉換為一個新的字符數組返回- static String valueOf(char[] data) :返回指定數組中表示該字符序列的 String
- static String valueOf(char[] data, int offset, int count) : 返回指定數組中表示該字符序列的 String
@Test
public void test4(){String s1 = "教育尚硅谷教育";System.out.println(s1.charAt(2)); // 尚// valueOf和copyValueOf源碼一模一樣的,就是用char數組new String(char[] ch)String s2 = String.valueOf(new char[]{'a', 'b', 'c'}); // abcString s3 = String.copyValueOf(new char[]{'a', 'b', 'c'}); // abc
}
5、開頭與結尾
boolean startsWith(xx)
:測試此字符串是否以指定的前綴開始boolean startsWith(String prefix, int toffset)
:測試此字符串從指定索引開始的子字符串是否以指定前綴開始boolean endsWith(xx)
:測試此字符串是否以指定的后綴結束
@Test
public void test5(){String s1 = "教育尚硅谷教育";System.out.println(s1.startsWith("教育a")); // falseSystem.out.println(s1.startsWith("教育",5)); // true
}
6、替換
String replace(char oldChar, char newChar)
:返回一個新的字符串,它是通過用 newChar 替換此字符串中出現的所有 oldChar 得到的。 不支持正則String replace(CharSequence target, CharSequence replacement)
:使用指定的字面值替換序列替換此字符串所有匹配字面值目標序列的子字符串String replaceAll(String regex, String replacement)
:使用給定的 replacement 替換此字符串所有匹配給定的正則表達式的子字符串String replaceFirst(String regex, String replacement)
:使用給定的 replacement 替換此字符串匹配給定的正則表達式的第一個子字符串
@Test
public void test6(){String s1 = "hello";String s2 = s1.replace('l', 'w');System.out.println(s1); // helloSystem.out.println(s2); // hewwoString s3 = s1.replace("ll", "wwww");System.out.println(s3); // hewwwwo
}
四、常見算法題
1、模擬一個trim方法,去除字符串兩端的空格
思路:查看字符串前綴后綴是否存在“ ”,去除后繼續判斷
public static String trimStr(String str) {while (str.startsWith(" ") || str.endsWith(" ")) {if (str.startsWith(" ")) {str = str.substring(1);}if (str.endsWith(" ")) {str = str.substring(0, str.length() - 1);}}return str;
}
2、將一個字符串進行反轉。將字符串中指定部分進行反轉。比如“abcdef
g”反轉為”abfedc
g”
方法一思路:字符串轉換為字符數組,從指定角標到結束角標,互換數據
public static String reversalStr(String str, int fromIndex, int toIndex) {char[] charArray = str.toCharArray();for (int i = fromIndex, j = toIndex; i < j; i++, j--) {char temp = charArray[i];charArray[i] = charArray[j];charArray[j] = temp;}return new String(charArray);
}
方法二思路:截取前中后三個字符串,中是需要反轉的,從新拼接,拼接中字符串時候,從后開始拼接
public static String reversalStr2(String str, int fromIndex, int toIndex) {String strReturn = str.substring(0, fromIndex);for (int i = toIndex; i >= fromIndex; i--) {strReturn += str.charAt(i);}strReturn += str.substring(toIndex + 1);return strReturn;
}
3、獲取一個字符串在另一個字符串中出現的次數。比如:獲取“ ab”在 “abkkcadkabkebfkabkskab” 中出現的次數
思路:獲取字符首次出現的角標,然后從出現的位置繼續向后找
public static int getCount(String str, String subStr) {int count = 0;int index = str.indexOf(subStr);while (index != -1) {index = str.indexOf(subStr, index + subStr.length());count++;}return count;
}
4、獲取兩個字符串中最大相同子串。比如:str1 = "abcwerthelloyuiodef“;str2 = “cvhellobnm”
思路:從小字符串下手,通過不同長度截取
public static String getMaxStr(String str1, String str2) {for (int i = 0; i < str2.length(); i++) {for (int x = 0, y = str2.length() - i - x; y <= str2.length(); x++, y++) {String substring = str2.substring(x, y);if (str1.contains(substring)) {return substring;}}}return null;
}
五、StringBuffer和StringBuilder
- 因為String對象是不可變對象,雖然可以共享常量對象,但是對于頻繁字符串的修改和拼接操作,效率極低,空間消耗也比較高
- 因此,JDK又在java.lang包提供了可變字符序列StringBuffer和StringBuilder類型
1、StringBuffer與StringBuilder的理解
- java.lang.StringBuffer代表
可變的字符序列
,JDK1.0中聲明 - 可以對字符串內容進行增刪,此時不會產生新的對象
//情況1:
String s = new String("我喜歡學習");
//情況2:
StringBuffer buffer = new StringBuffer("我喜歡學習");
buffer.append("數學");
- StringBuilder 和 StringBuffer 非常類似,均代表可變的字符序列,而且提供相關功能的方法也一樣
- 區分String、StringBuffer、StringBuilder
- String:不可變的字符序列; 底層使用char[]數組存儲(JDK8.0中)
- StringBuffer:可變的字符序列;線程安全(方法有synchronized修飾),效率低;底層使用char[]數組存儲 (JDK8.0中)
- StringBuilder:可變的字符序列; jdk1.5引入,線程不安全的,效率高;底層使用char[]數組存儲(JDK8.0中)
2、StringBuilder、StringBuffer的API
StringBuilder、StringBuffer的API是完全一致的,并且很多方法與String相同
常用API
- StringBuffer append(xx):提供了很多的append()方法,用于進行字符串追加的方式拼接
- StringBuffer delete(int start, int end):刪除[start,end)之間字符
- StringBuffer deleteCharAt(int index):刪除[index]位置字符
- StringBuffer replace(int start, int end, String str):替換[start,end)范圍的字符序列為str
- void setCharAt(int index, char c):替換[index]位置字符
- char charAt(int index):查找指定index位置上的字符
- StringBuffer insert(int index, xx):在[index]位置插入xx
- int length():返回存儲的字符數據的長度
- StringBuffer reverse():反轉
@Test
public void test1(){StringBuilder sBuilder = new StringBuilder();sBuilder.append("abc").append("123").append("def"); //方法鏈的調用System.out.println(sBuilder); StringBuilder sBuilder = new StringBuilder("hello");sBuilder.insert(2, "中");System.out.println(sBuilder); // he中lloStringBuilder sBuilder1 = sBuilder.reverse();System.out.println("反轉字符串:" + sBuilder); // oll中ehSystem.out.println("反轉返回字符串:" + sBuilder1); // oll中ehSystem.out.println("反轉字符串是否與返回字符串是同一個對象:" + (sBuilder == sBuilder1)); // trueSystem.out.println("字符串長度:" + sBuilder.length()); //實際存儲的字符的個數 // 6
}
其它API
- 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的最后一次出現下標
- String substring(int start):截取當前字符序列[start,最后]
- String substring(int start, int end):截取當前字符序列[start,end)
- String toString():返回此序列中數據的字符串表示形式
- void setLength(int newLength) :設置當前字符序列長度為newLength
3、效率測試
測試String、StringBuffer、StringBuilder在操作數據方面的效率
@Test
public void test4() {//初始設置long startTime = 0L;long endTime = 0L;String text = "";StringBuffer buffer = new StringBuffer("");StringBuilder builder = new StringBuilder("");//開始對比startTime = System.currentTimeMillis();for (int i = 0; i < 20000; i++) {buffer.append(String.valueOf(i));}endTime = System.currentTimeMillis();System.out.println("StringBuffer的執行時間:" + (endTime - startTime));startTime = System.currentTimeMillis();for (int i = 0; i < 20000; i++) {builder.append(String.valueOf(i));}endTime = System.currentTimeMillis();System.out.println("StringBuilder的執行時間:" + (endTime - startTime));startTime = System.currentTimeMillis();for (int i = 0; i < 20000; i++) {text = text + i;}endTime = System.currentTimeMillis();System.out.println("String的執行時間:" + (endTime - startTime));
}
輸出結果:
StringBuffer的執行時間:14
StringBuilder的執行時間:2
String的執行時間:264