參考鏈接: Java中的StringBuffer appendCodePoint()方法以及示例
JDK8在線Api中文手冊?
JDK8在線Api英文手冊?
?
?Java中的字符串處理
?1.1 String類的構造函數1.2 字符串的長度1.3 特殊的字符串操作1.3.1 字符串字面值1.3.2 字符串連接1.3.3 字符串和其他數據類型的連接1.3.4 字符串轉換和toString()方法
? ? ? 1.4 提取字符串1.4.1 charAt()1.4.2 getChars()1.4.3 getBytes()1.4.4 toCharArray()
? ? ? 1.5 比較字符串1.5.1 equals()和equalsIgnoreCase()1.5.2 regionMatches()1.5.3 startsWith()和endsWith()1.5.4 equals()與==1.5.6 compareTo()
? ? ? 1.6 查找字符串1.7 修改字符串1.7.1 substring()1.7.2 concat()1.7.3 replace()1.7.4 trim()
? ? ? 1.8 使用valueOf()轉換數據1.9 改變字符串中字符的大小寫1.10 連接字符串1.11 其他String方法1.12 StringBuffer類1.12.1 StringBuffer類的構造函數1.12.2 length() 與 capacity()1.12.3 ensureCapacity()1.12.4 setLength()1.12.5 charAt() 與 setCharAt()1.12.6 getChars()1.12.7 append()1.12.8 insert()1.12.9 reverse()1.12.10 delete() 與 deleteCharAt()1.12.11 replace()1.12.12 substring()1.12.13 其他StringBuffer方法
? ? ? 1.13 StringBuilder類
? ??
? ?
??
?
?
? ? 與大多數其他編程語言一樣,在Java中,字符串也是一連串的字符。但是,不像其他語言一樣作為字符數組實現字符串,Java將字符串實現為String類型的對象。
? ? 作為內置對象實現字符串,使得Java可以提供許多方便字符串處理的特性。例如,Java提供了用于比較兩個字符串、查找子串、連接兩個字符串以及改變字符串中字母大小寫的方法。此外,可以通過多種方式構造String對象,從而當需要時可以很容易地獲取字符串。
? ? 當創建String對象時,創建的字符串不能修改。也就是說,一旦創建一個String對象,就不能改變這個字符串中包含的字符。乍一看,這好像有一個嚴重的限制。但是,情況并非如此。仍然可以執行各種字符串操作。區別是,當每次需要已存在字符串的修改版本時,會創建包含修改后內容的新String對象。原始字符串保持不變。使用這種方式的原因是:實現固定的,不能修改的字符串與實現能修改的字符串相比較效率更高。對于那些需要能夠修改的字符串的情況,Java提供了兩個選擇:StringBuffer和StringBuilder,這兩個類用來保存在創建之后可以進行修改的字符串。
? ? String、StringBuffer、StringBuilder類都是在java.lang中定義的。因此,所有程序自動都可以使用它們。所有這些類被聲明為final,這意味著這些類不能有子類。這使得對于通用的字符串操作,可以采取特定的優化以提高性能。這3個類實現了CharSequence接口。
? ? 最后一點,所謂String類型對象中的字符串是不可改變的,是指創建了String實例后不能修改String實例的內容。但是,在任何時候都可以修改String引用變量,使其指向其他String對象。
?
1.1 String類的構造函數?
? ?String類支持幾個構造函數。為了創建空的String,可以調用默認構造函數。例如:?
String s = new String();
?
? ?將創建內部沒有任何字符的String實例。? ? 經常會希望創建具有初始化值的字符串。String類提供了各種構造函數來解決這個問題。為了創建由字符數組初始化的String實例,可以使用如下所示的構造函數:?
String(char chars[])
?
? ?下面是一個例子:?
char chars[] = {'a','b','c'};
String s = new String(chars);
?
? ?這個構造函數使用字符串"abc"初始化s。? ? 使用下面的構造函數,可以指定字符數組的子范圍作為初始化部分:?
String(char chars[],int startIndex,int numChars)
?
? ?其中,startIndex指定了子范圍開始位置的索引,numChars指定了使用的字符數量。下面是一個例子:?
char chars[] = {'a','b','c','d','e','f'};
String s = new String(chars,2,3);
?
? ?這會使用字符cde初始化s。? ? 使用下面這個構造函數,可以構造與另外一個String對象包含相同字符的String對象:?
String(String strOb)
?
? ?在此,strObj是一個String對象。分析下面這個例子:?
//Construct one String from another
class MakeString {
?public static void main(String[] args) {
? ? ? char c[] ={'J','a','v','a'};
? ? ? String s1 = new String(c);
? ? ? String s2 = new String(s1);
? ? ? System.out.println(s1);
? ? ? System.out.println(s2);
? ? ? /**
? ? ? ?* 輸出:
? ? ? ?* Java
? ? ? ?* Java
? ? ? ?*/
? }
}
?
? ?可以看出,s1和s2包含相同的字符串。? ? 盡管Java的char類型使用16位表示基本的Unicode字符集,但是在Internet上,字符串的典型格式是使用從ASCII字符集構造的8位字節數組。因為8位的ASCII字符串很普遍,所以String類提供了使用字節數組初始化字符串的構造函數。下面是其中的兩種形式:?
String(byte chrs[])
String(byte chrs[],int startIndex,int numChars)
?
? ?在此,chrs指定字節數組。上面的第二種形式允許指定子范圍。在這兩個構造函數中,從字節到字符的轉換是使用平臺的默認字符編碼完成的。下面程序演示了這些構造函數的使用:?
//Construct string from subset of char array.
class SubStringCons {
? public static void main(String[] args) {
? ? ? byte ascii[]={65,66,67,68,69,70};
? ? ? String s1 = new String(ascii);
? ? ? System.out.println(s1);
? ? ? String s2 = new String(ascii,2,3);
? ? ? System.out.println(s2);
? ? ? /**
? ? ? ?* 輸出
? ? ? ?* ABCDEF
? ? ? ?* CDE
? ? ? ?*/
? }
}
?
? ?Java還定義了字節到字符串(byte-to-string)構造函數的擴展版本,在擴展版本中可以指定字符的編碼方式,這決定了如何將字節轉換成字符。但是,通常會希望使用平臺提供的默認編碼方式。? ? 注意? ? 無論何時,從數組創建String對象都會復制數組的內容。在創建字符串之后,如果修改數組的內容,String對象不會發生變化。? ? 使用下面的構造函數,可以從StringBuffer構造String實例:?
String(StringBuffer strBufObj)
?
? ?使用下面這個構造函數,可以從StringBuilder構造String實例:?
String(StringBulider strBuildObj)
?
? ?下面的構造函數支持擴展Unicode字符集:?
String(int codePoints[],int startIndex,int numChars)
?
? ?其中codePoints是包含Unicode代碼點的數組。結果字符串從startIndex開始,截取numChars個字符。? ? Java還定義了允許指定Charset的構造函數。?
1.2 字符串的長度?
? ?字符串的長度是指字符串所包含字符的數量。為了獲取這個值,調用length()方法,如下所示:?
int length()
?
1.3 特殊的字符串操作?
? ?因為字符串在編程中十分常見,也很重要,所以Java語言在語法中為一些字符串操作添加了特殊的支持。這些操作包括從字符串字面值自動創建新的String實例,使用"+"運算符連接多個字符串,以及將其他數據類型轉換為字符串表示形式。盡管有顯式的方法可以執行這些操作,但是Java可以自動完成這些操作,從而程序員提供便利并增加代碼的清晰度。?
1.3.1 字符串字面值?
? ?前面的例子顯示了如何使用new運算符從字符數組顯示地創建String實例。但是,還有更容易的方式,即使用字符串字面值。對于程序中的每個字符串字面值,Java會自動構造String對象。因此,可以使用字符串字面值初始化String對象。例如,下面的代碼段創建了兩個相等的字符串:?
char chars[] = {'a','b','c'};
String s1 = new String(chars);
String s2 = "abc";//use string literal
?
? ?因為會為每個字符串字面值創建String對象,所以在能夠使用String對象的任何地方都可以使用字符串字面值。例如,可以直接對加引號的字符串調用方法,就好像它們是對象引用一樣,如下面的語句所示。下面的代碼對字符串"abc"調用length()方法。正如所期望的那樣,該語句輸出"3"。?
System.out.println("abc".length());
?
1.3.2 字符串連接?
? ?一般而言,Java不允許為String對象應用運算符。這個規則的一個例外是"+“運算符,”+“運算符可連接兩個字符串,生成一個String對象作為結果。還可以將一系列”+"運算符連接在一起。例如,下面的代碼段連接3個字符串:?
String age = "9";
String s = "He is" + age + " years old.";
System.out.println(s);
?
? ?上面的代碼會顯示字符串"He is 9 years old."?
1.3.3 字符串和其他數據類型的連接?
? ?可以將字符串和其他類型數據連接起來。例如,分析與前面例子稍微不同的版本。?
int age = 9;
String s = "He is" + age + " years old.";
System.out.println(s);
?
? ?首先,age是int類型,而不是String類型,但是生成的輸出和前面的例子相同。這是因為age中的int值會在String對象中被自動轉換成相應的字符串表示形式。然后再像以前那樣連接這個字符串。只要"+"運算符的其他操作數是String實例,編譯器就會把操作數轉換為相應的字符串等價形式。? ? 但是,當將其他類型的操作和字符串連接表達式混合到一起時,應當小心。可能會得到出乎意料的結果,分析下面的代碼:?
String s = "four: " + 2 + 2;
System.out.println(s)
?
? ?該代碼會顯示:? ? front: 22? ? 而不是我們可能期望的:? ? front: 4? ? 下面是其中的原因。運算符優先級導致首先連接"four"和2的字符串等價形式,然后再將這個運算的結果和2的字符串等價形式連接起來。為了首先完成整數相加運算,必須使用圓括號,像下面這樣:?
String s = "four: " + (2 + 2);
?
? ?現在s包含字符串"four: 4"?
1.3.4 字符串轉換和toString()方法?
? ?當Java在執行連接操作期間,將數據轉換成相應的字符串表示形式時,是通過調用String定義的字符串轉換方式valueOf()的某個重載版本來完成的。valueOf()針對所有基本類型以及Object類型進行了重載。對于基本類型,valueOf()方法返回一個字符串,該字符串包含與調用值等價的人類可以閱讀的形式。對于對象,valueOf()方法調用對象的toString()方法。toString()方法決定了所有創建類對象的字符串表示形式。? ? 每個類都實現了toString()方法,因為該方法是由Object定義的。然而,toString()方法的默認實現很少能夠滿足需要。對于自己創建的大多數重要類,我們可能希望重寫toString()方法并提供自己的字符串表示形式。幸運的是,這很容易完成。toString()方法的一般形式如下:?
String toString()
?
? ?為了實現toString()方法,可簡單地返回一個String對象,使其包含用來描述自定義類對象的人類可閱讀的字符串。? ? 為創建的類重寫toString()方法,可以將其完全集成到Java開發環境中。例如,可以把它們用于print()和println()語句,還可以用于字符串連接表達式中。下面的程序通過Box類重寫toString()方法,演示了這一點:?
//Override toString() for Box class.
class Box {
? ?double width;
? ?double height;
? ?double depth;
? ?Box(double w, double h, double d) {
? ? ? ?width = w;
? ? ? ?height = h;
? ? ? ?depth = h;
? ?}
? ?@Override
? ?public String toString() {
? ? ? ?return "Dimensions are " + width + " by " + depth + " by " + height + ".";
? ?}
}
class toStringDemo {
?public static void main(String[] args) {
? ? ? Box b = new Box(10, 12, 14);
? ? ? String s = "Box b:" + b;//concatenate Box object
? ? ? System.out.println(b);//convert Box to string
? ? ? System.out.println(s);
? ? ? /**
? ? ? ?* 輸出:
? ? ? ?* Dimensions are 10.0 by 12.0 by 12.0.
? ? ? ?* Box b:Dimensions are 10.0 by 12.0 by 12.0.
? ? ? ?*/
? }
}
?
? ?可以看出,在連接表達式或println()調用中使用Box對象時,會自動調用Box的toString()方法。?
1.4 提取字符串?
? ?String類提供了大量方法,用于從String對象中提取字符。在此介紹其中的幾個。盡管不能向索引數組中的字符那樣,索引構成String對象中字符串的字符,但是許多String方法為字符串使用索引(或偏移)來完成它們的操作。和數組一樣,字符串索引也是從0開始的。?
1.4.1 charAt()?
? ?為了從字符串中提取單個字符,可以通過charAt()方法直接引用某個單個字符。該方法的一般形式如下:?
char charAt(int where)
?
? ?其中,where是希望獲取的字符的索引,where的值必須是非負的,并且能夠指定字符串中的一個位置,charAt()方法返回指定位置的字符。例如:?
char ch;
ch = "abc".charAt(1);
?
? ?將b賦給ch。?
1.4.2 getChars()?
? ?如果希望一次提取多個字符,可以使用getChars()方法。它的一般形式為:?
void getChars(int sourceStart,int sourceEnd,char target[],int targetStart)
?
? ?其中sourceStart指定了子串的開始索引,sourceEnd指定了子串末尾之后下一個字符的索引。因此,子串包含字符串中索引從sourceStart到sourceEnd-1之間的字符。target指定了接收字符的數組。在target中開始復制子串的索引是由targetStart傳遞的。注意必須確保target數組足夠大,以容納指定子串的字符。?
class getCharsDemo {
? public static void main(String[] args) {
? ? ? ?String s = "This is a demo of the getChars method.";
? ? ? ?int start = 10;
? ? ? ?int end = 14;
? ? ? ?char buf[] = new char[end - start];
? ? ? ?s.getChars(start, end, buf, 0);
? ? ? ?System.out.println(buf);
? ? ? ?/**
? ? ? ? * 輸出:
? ? ? ? * demo
? ? ? ? */
? ?}
}
?
1.4.3 getBytes()?
? ?getChars()的一種替代選擇是將字符保存在字節數組中。這個方法是getBytes(),它使用平臺提供的從字符到字節轉換的默認方法。下面是getBytes()方法最簡單的形式:?
byte[] getBytes()
?
? ?getBytes()方法還有其他形式。當將String值導出到不支持16位Unicode字符的環境中時,最常使用getBytes()方法。例如,大部分Internet協議和文本文件格式為文本交互使用8位ASCII碼。?
1.4.4 toCharArray()?
? ?如果希望將String對象中的所有字符轉換位字符數組,最簡單的方法是調用toCharArray()。該方法為整個字符串返回字符數組,它的一般形式如下:?
char[] toCharArray()
?
? ?這個方法是為了方便操作而提供的,因為可以使用getChars()得到相同的結果。?
1.5 比較字符串?
? ?String類提供了大量用來比較字符串或字符串中子串的方法,在此將介紹其中的幾個。?
1.5.1 equals()和equalsIgnoreCase()?
? ?為了比較兩個字符串是否相等,可以使用equals()方法,它的一般形式如下:?
boolean equals(Object str)
?
? ?其中,str是將要與調用String對象進行比較的String對象。如果字符串以相同的順序包含相同的字符,該方法返回true,否則返回false。比較是大小寫敏感的。? ? 為了執行忽略大小寫區別的比較,可以調用equalsIgnoreCase()。該方法在比較兩個字符串時,認為A-Z和a-z是相同的,它的一般形式如下:?
boolean equalsIgnoreCase(String str)
?
? ?其中,str是將要與調用String對象進行比較的String對象。如果字符串以相同的順序包含相同的字符,該方法返回true,否則返回false。? ? 下面是演示equals()和equalsIgnoreCase()的例子:?
//Demonstrate equals() and equalsIgnoreCase().
class equalsDemo {
? public static void main(String[] args) {
? ? ? ?String s1 = "Hello";
? ? ? ?String s2 = "Hello";
? ? ? ?String s3 = "Good-bye";
? ? ? ?String s4 = "HELLO";
? ? ? ?System.out.println(s1 + " equals " + s2 + " -> "+s1.equals(s2));
? ? ? ?System.out.println(s1 + " equals " + s3 + " -> "+s1.equals(s3));
? ? ? ?System.out.println(s1 + " equals " + s4 + " -> "+s1.equals(s4));
? ? ? ?System.out.println(s1 + " equalsIgnoreCase " + s4 + " -> "+s1.equalsIgnoreCase(s4));
? ? ? ?/**
? ? ? ? * 輸出:
? ? ? ? * Hello equals Hello -> true
? ? ? ? * Hello equals Good-bye -> false
? ? ? ? * Hello equals HELLO -> false
? ? ? ? * Hello equalsIgnoreCase HELLO -> true
? ? ? ? */
? ?}
}
?
1.5.2 regionMatches()?
? ?regionMatches()方法比較字符串中某個特定部分與另一個字符串中的另一個特定部分。該方法還有一種重載形式,允許在這種比較中忽略大小寫。這個方法的一般形式為:?
boolean regionMatches(int startIndex,String str2,int str2StartIndex,int numChars)
boolean regionMatches(boolean ignoreCase,int startIndex,String str2,int str2StartIndex,int numChars)
?
? ?對于這兩個版本,startIndex指定了調用String對象中比較部分開始的索引位置,,將與之進行比較的String對象是由str2指定的。str2中開始進行比較的索引位置是由str2StartIndex指定的。將要進行比較的子串的長度是由numChars傳遞的。在第二個版本中,如果ignoreCase為true,那么忽略字符的大小寫;否則,大小寫就是有意義的。?
1.5.3 startsWith()和endsWith()?
? ?String定義了兩個方法,它們大體上是regionMatches()方法的特定形式。startsWith()方法確定給定的String對象是否以指定的字符串開始。與之相反,endsWith()方法確定String對象是否以指定的字符串結束。它們的一般形式如下:?
boolean startsWith(String str)
boolean endsWith(String str)
?
? ?其中,str是將進行測試的String對象。如果字符串匹配,就返回true;否則返回false。例如:?
"Foobar".endsWith("bar")
?
? ?和?
"Foobar".startsWith("Foo")
?
? ?都返回true。? ? 下面是startsWith()方法的第二種形式,這種形式允許指定開始位置:?
boolean startsWith(String str,int startIndex)
?
? ?其中,startsIndex指定了在調用字符串中要開始查找位置的索引。例如:?
"Foobar".startsWith("bar",3)
?
? ?返回true。?
1.5.4 equals()與==?
? ?equals()方法與“==”運算符執行不同的操作,理解這一點很重要。剛才解釋過,equals()方法比較String對象中的字符。雙等號運算符比較對兩個對象的引用,查看它們是否指向相同的實例。下面的程序演示了兩個不同的String對象包含相同字符,但是如果過對這些對象的引用進行比較,就會發現它們是不相等的:?
//equals vs ==
class EqualsNotEqualTo {
? public static void main(String[] args) {
? ? ? ?String s1 = "Hello";
? ? ? ?String s2 = new String(s1);
? ? ? ?System.out.println(s1 + " equals " + s2 + " -> " + s1.equals(s2));
? ? ? ?System.out.println(s1 + " == " + s2 + " -> " + (s1 == s2));
? ? ? ?/**
? ? ? ? * 輸出:
? ? ? ? * Hello equals Hello -> true
? ? ? ? * Hello == Hello -> false
? ? ? ? */
? ?}
}
?
? ?變量s1引用由"Hello"創建的String實例,s2引用的對象是使用s1作為初始化器創建的。因此,兩個String對象的內容是相同的,但它們是不同的對象。這意味著s1和s2引用的是不同的對象,所以不是"=="的關系,正如前面程序的輸出所展示的。?
1.5.6 compareTo()?
? ?通常,只知道兩個字符串是否相同是不夠的。對于排序應用,需要知道哪個字符串小于、等于或大于下一個字符串。根據字典順序,如果一個字符串位于另一個字符串的前面,那么這個字符串小于另一個字符串;如果一個字符串位于另一個字符串的后面,那么這個字符串大于另一個字符串。方法compareTo()就是用于這個目的,該方法是由Comparable<T>接口定義的,String實現了這個接口。compareTo()方法的一般形式如下:?
int compareTo(String str)
?
? ?其中,str是將要與調用String對象進行比較的String對象。返回的比較結果給及相應解釋如下表所示:?
?
?compareTo()方法的返回結果
?
值含義小于0調用字符串小于str大于0調用字符串大于str0兩個字符串相等
? ?下面是一個對數組中的字符串進行排序的示例程序。該程序使用compareTo()方法為冒泡排序法確定排列順序:?
//A bubble sort for Strings.
class SortString {
static String arr[] = {"Now", "is", "the", "for", "all",
? ? ? ? ? "good", "men", "to", "come", "to", "the", "aid"
? ? ? ? ? , "of", "their", "country"};
?
? public static void main(String[] args) {
? ? ? for (int j = 0; j < arr.length; j++) {
? ? ? ? ? for (int i = j + 1; i < arr.length; i++) {
? ? ? ? ? ? ? if (arr[i].compareTo(arr[j]) < 0) {
? ? ? ? ? ? ? ? ? String t = arr[j];
? ? ? ? ? ? ? ? ? arr[j] = arr[i];
? ? ? ? ? ? ? ? ? arr[i] = t;
? ? ? ? ? ? ? }
? ? ? ? ? }
? ? ? ? ? System.out.println(arr[j]);
? ? ? }
? ? ? /**
? ? ? ?* 輸出:
? ? ? ?* Now
? ? ? ?* aid
? ? ? ?* all
? ? ? ?* come
? ? ? ?* country
? ? ? ?* for
? ? ? ?* good
? ? ? ?* is
? ? ? ?* men
? ? ? ?* of
? ? ? ?* the
? ? ? ?* the
? ? ? ?* their
? ? ? ?* to
? ? ? ?* to
? ? ? ?*/
? }
}
?
? ?從這個例子的輸出可以看出,compareTo()考慮字母的大小寫。單詞"Now"出現在所有其他單詞之前,因為它是以大寫字母開頭的,這意味著在ASCII字符集中它具有更小的值。? ? 當比較兩個字符串時,如果希望忽略大小寫區別,可以使用compareToIgnoreCase(),如下所示:?
int compareToIgnoreCase(String str)
?
? ?除了忽略大小寫外,這個方法的返回結果與compareTo()相同。如果在前面的程序中使用這個方法的話,"Now"將不再是第一個單詞。?
1.6 查找字符串?
? ?String類提供了兩個用于在字符串中查找指定字符或子串的方法:?
indexOf():查找字符或字符串第一次出現時的索引。lastIndexOf():查找字符和子串最后一次出現時的索引。? ? 這兩個方法都以不同的方式進行了重載。對于所有情況,這些方法都返回發現字符或子串時的索引位置,或返回-1表示查找失敗。? ? 為了查找字符第一次出現時的索引,使用:?
int indexOf(int ch)
?
? ?為了查找字符最后一次出現時的索引,使用:?
int lastIndexOf(int ch)
?
? ?其中,ch是將要查找的字符。? ? 為了查找子串第一次或最后一次出現時的索引,使用:?
int indexOf(String str)
int lastIndexOf(String str)
?
? ?其中,str指定了將要查找的子串。? ? 可以使用下面這些形式執行查找開始時的索引:?
int indexOf(int ch,int startIndex)
int lastIndexOf(int ch,int startIndex)
int indexOf(String str,int startIndex)
int lastIndexOf(String str,int startIndex)
?
? ?其中,startIndex指定了開始查找時的位置索引。對于indexOf(),查找操作從startIndex索引位置運行到字符串的末尾。對于lastIndexOf(),查找操作從startIndex運行到索引位置0。? ? 下面的例子展示了如何使用各種索引方法在String內部進行查找:?
//Demonstrate indexOf() and lastIndexOf().
class indexOfDemo {
?public static void main(String[] args) {
? ? ? String s = "Now is the time for all good men "
? ? ? ? ? ? ? + "to come to the aid of their country.";
? ? ? System.out.println(s);
? ? ? System.out.println("indexOf(t) = " + s.indexOf('t'));
? ? ? System.out.println("lastIndexOf(t) = " + s.lastIndexOf('t'));
? ? ? System.out.println("indexOf(the) = " + s.indexOf("the"));
? ? ? System.out.println("lastIndexOf(the) = " + s.lastIndexOf("the"));
? ? ? System.out.println("indexOf(t,10) = " + s.indexOf('t', 10));
? ? ? System.out.println("lastIndexOf(t,60) = " + s.lastIndexOf('t', 60));
? ? ? System.out.println("indexOf(the,10) = " + s.indexOf("the", 10));
? ? ? System.out.println("lastIndexOf(the,60) = " + s.lastIndexOf("the", 60));
? ? ? /**
? ? ? ?* 輸出:
? ? ? ?*Now is the time for all good men to come to the aid of their country.
? ? ? ?* indexOf(t) = 7
? ? ? ?* lastIndexOf(t) = 65
? ? ? ?* indexOf(the) = 7
? ? ? ?* lastIndexOf(the) = 55
? ? ? ?* indexOf(t,10) = 11
? ? ? ?* lastIndexOf(t,60) = 55
? ? ? ?* indexOf(the,10) = 44
? ? ? ?* lastIndexOf(the,60) = 55
? ? ? ?*/
? }
}
?
1.7 修改字符串?
? ?因為String對象是不可改變的,所以當希望修改String對象時,必須將之復制到StringBuffer或StringBuilder對象中,或者使用String類提供的方法來構造字符串修改后的新副本。下面介紹這些方法中的幾個。?
1.7.1 substring()?
? ?使用substring方法可以提取子串。它有兩種形式,第一種形式如下:?
String substring(int startIndex)
?
? ?其中,startIndex指定了子串開始時的位置索引。這種形式返回調用字符串中從startIndex索引位置開始到字符串末尾的子串副本。? ? substring()方法的第二種形式允許同時指定子串的開始索引和結束索引:?
String substring(int startIndex,int endIndex)
?
? ?其中,startIndex指定開始索引,endIndex指定結束索引。返回的字符串包含從開始索引到結束索引的字符,但是不包含結束索引位置的字符。? ? 下面的程序使用substring()方法在一個字符串中使用一個字符串替換另一個子串的所有實例:?
//Substring replacement.
class StringReplace {
? public static void main(String[] args) {
? ? ? ?String org = "This is a test. This is, too.";
? ? ? ?String search = "is";
? ? ? ?String sub = "was";
? ? ? ?String result = "";
? ? ? ?int i;
? ? ? ?do {//replace all matching substrings
? ? ? ? ? ?System.out.println(org);
? ? ? ? ? ?i = org.indexOf(search);
? ? ? ? ? ?if (i != -1) {
? ? ? ? ? ? ? ?result = org.substring(0, i);
? ? ? ? ? ? ? ?result = result + sub;
? ? ? ? ? ? ? ?result = result + org.substring(i + search.length());
? ? ? ? ? ? ? ?org = result;
? ? ? ? ? ?}
? ? ? ?} while (i != -1);
? ? ? ?/**
? ? ? ? * This is a test. This is, too.
? ? ? ? * Thwas is a test. This is, too.
? ? ? ? * Thwas was a test. This is, too.
? ? ? ? * Thwas was a test. Thwas is, too.
? ? ? ? * Thwas was a test. Thwas was, too.
? ? ? ? */
? ?}
}
?
1.7.2 concat()?
? ?可以使用concat()方法來連接兩個字符串,如下所示:?
String concat(String str)
?
? ?該方法創建一個新對象,這個新對象包含調用字符串并將str的內容追加到結尾。concat()與"+"執行相同的功能。例如:?
String s1 = "one";
String s2 = s1.concat("two");
?
? ?將字符串"onetwo"存放發s2中。與下面語句產生的結果相同:?
String s1 = "one";
String s2 = s1 + "two";
?
1.7.3 replace()?
? ?replace()方法有兩種形式。第一種形式在調用字符串中使用一個字符代替另一個字符的所有實例,一般形式如下:?
String replace(char original,char replacement)
?
? ?其中,original指定將被替換的字符,replacement指定替換字符,結果字符串將被返回。例如:?
String s = "Hello".replace('1','w')
?
? ?將字符串"Hewwo"存放到s中。? ? replace()方法的第二種形式使用一個字符序列代替另一個字符序列,一般形式如下:?
String replace(CharSequence original,CharSequence replacement)
?
1.7.4 trim()?
? ?trim()方法返回調用字符串的副本,并移除開頭和結尾的所有空白字符,一般形式如下:?
String trim()
?
? ?下面是一個例子:?
String s = " Hello World ".trim();
?
? ?這條語句將字符創"Hello World"存放到s中。? ? 當處理用戶命令時,trim()方法特別有用。例如,下面的程序用戶輸入某個州的名稱,然后顯示該州的首府。該程序使用trim()方法移除用戶可能無意中輸入的開頭和結尾的所有空白字符。?
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
?
//Using trim() to process commands.
class UserTrim {
?public static void main(String[] args) throws IOException {
? ? ? //create a BufferedReader using System.in
? ? ? BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
? ? ? String str;
? ? ? System.out.println("Enter 'stop' to quit.");
? ? ? System.out.println("Enter State: ");
? ? ? do {
? ? ? ? ? str = br.readLine();
? ? ? ? ? str = str.trim();//remove whitespace
? ? ? ? ? if (str.equals("Illinois"))
? ? ? ? ? ? ? System.out.println("Capital is Springfield.");
? ? ? ? ? else if (str.equals("Missouri"))
? ? ? ? ? ? ? System.out.println("Capital is Jefferson City");
? ? ? ? ? else if (str.equals("California"))
? ? ? ? ? ? ? System.out.println("Capital is Sacramento.");
? ? ? ? ? //...
? ? ? } while (!str.equals("stop"));
? }
}
?
1.8 使用valueOf()轉換數據?
? ?valueOf()方法將數據從內部格式轉換成人類可以閱讀的形式。valueOf()是靜態方法,String針對所有Java內置類型對該方法進行了重載,從而可以將每種類型正確地轉換成字符串。Java還針對Object類型對valueOf()方法進行了重載,從而使您創建的所有類類型的對象都可作為valueOf()方法的參數(Object是所有類的超類)。下面是valueOf()方法的幾種形式:?
static String valueOf(double num)
static String valueOf(long num)
static String valueOf(Object ob)
static String valueOf(char chars[])
?
? ?前面討論過,當需要其他類型數據的字符串表示形式時會調用valueOf()方法,例如在連接操作期間。可以使用任何數據類型直接調用valueOf()方法,從而得到可讀的字符串表示形式。所有簡單類型都被轉換成它們通用的字符串表示形式。傳遞給valueOf()方法的所有對象都將返回調用對象的toString()方法的結果。實際上,可以直接調用toString()方法得到相同的結果。? ? 對于大部分數組,valueOf()方法會返回一個相當隱蔽的字符串,以表明這是某種類型的數組。然而,對于字符數組,會創建包含字符數組的String對象。還有一個特殊版本的valueOf()方法,允許指定字符數組的子集,一般形式為:?
static String valueOf(char chars[],int startIndex,int numChars)
?
? ?其中,chars是包含字符的數組,startIndex是期望子串在字符數組中何處開始的位置索引,numChars指定了子串的長度。?
1.9 改變字符串中字符的大小寫?
? ?方法toLowerCase()將字符串中的所有字符從大寫改變為小寫,方法toUpperCase()將字符串中的所有字符從小寫改為大寫。非字母字符不受影響。下面是這些方法的最簡單形式:?
String toLowerCase()
String toUpperCase()
?
? ?這些方法返回String對象,其中包含與調用字符串等價的大寫或小寫形式。對于這兩種情況下,都是由默認區域設置控制轉換。?
//Demonstrate toUpperCase() and toLowerCase().
class ChangeCase {
? public static void main(String[] args) {
? ? ? ?String s = "This is a test.";
? ? ? ?System.out.println("Original: " + s);
? ? ? ?String upper = s.toUpperCase();
? ? ? ?String lower = s.toLowerCase();
? ? ? ?System.out.println("UpperCase: " + upper);
? ? ? ?System.out.println("LowerCase: " + lower);
? ? ? ?/**
? ? ? ? * 輸出:
? ? ? ? * Original: This is a test.
? ? ? ? * UpperCase: THIS IS A TEST.
? ? ? ? * LowerCase: this is a test.
? ? ? ? */
? ?}
}
?
? ?另外一點:toLowerCase()和toUpperCase()方法的重載版本,還允許指定控制轉換的Locale對象。對于某些情況,指定區域非常重要,和有助于國際化應用程序?
1.10 連接字符串?
? ?JDK 8 為String類添加了一個新方法join(),用于連接兩個或更多個字符串,并使用分隔符分隔各個字符串,如空格或逗號。join()方法有兩種形式,第一種形式如下所示:?
static String join(CharSequence delim,CharSequence ...strs)
?
? ?其中,delim指定了分隔符,用于分隔strs指定的字符序列。因為String類實現了CharSequence接口,所以strs可以是一個字符串列表,下面的程序演示了這個版本的join()方法:?
//Demonstrate the join() method defined by String.
class StringJoinDemo {
? public static void main(String[] args) {
? ? ? ?String result = String.join(" ", "Alpha", "Beta", "Gamma");
? ? ? ?System.out.println(result);
? ? ? ?result = String.join(", ", "John", "ID#: 569",
? ? ? ? ? ? ? ?"E-mail: 123@qq.com");
? ? ? ?System.out.println(result);
? ? ? ?/**
? ? ? ? * 輸出:
? ? ? ? * Alpha Beta Gamma
? ? ? ? * John, ID#: 569, E-mail: 123@qq.com
? ? ? ? */
? ?}
}
?
? ?第一次調用join()時,在每個字符串之間插入了空格。在第二次調時,指定分隔符為一個逗號加一個空格,這表明分隔符并非只能是一個字符。? ? join()方法的第二種形式允許連接從實現了Iterable接口的對象獲取的一個字符串列表。?
1.11 其他String方法?
? ?除了前面討論的方法外,String類還提供了許多其他方法。如下表所示:?
?
?String類的其他方法
?
方法描述int codePointAt(int i)返回由i指定的位置的Unicode代碼點int codePointBefore(int i)返回由i指定的位置之前的Unicode代碼點int codePointCount(int start,int end)返回調用字符串處于start到end-1索引范圍內的代碼代碼點數boolean contains(CharSequence str)如果調用字符串包含由str指定的字符串,就返回true;否則返回falseboolean contentEquals(CharSequence str)如果調用字符串和str包含的字符串相同,就返回true;否則返回falseboolean contentEquals(StringBuffer str)如果字符串和str包含的字符串相同,就返回true;否則返回falsestatic String format(String fmtstr,Object …args)返回格式化的字符串,由fmtstr指定static String format(Locale loc,String fmtstr,Object …args)返回格式化的字符串,由fmtstr指定。格式化是由loc指定的區域控制的boolean isEmpty()如果調用字符串沒有任何字符并且長度為0,就返回trueboolean matches(String regExp)如果調用字符串和regExp傳遞的正則表達式匹配,就返回true;否則返回falseint offsetByCodePoints(int start,int num)返回字符串中超過start所指定開始索引num個代碼點的索引String replaceFirst(String regExp,String newStr)返回一個字符串,在返回的這個字符串中,使用newStr替換與regExp所指定正則表達式匹配的第一個子串String replaceAll(String regExp,String newStr)返回一個字符串,在返回的這個字符串中,使用newStr替換與regExp所指定正在表達式匹配的所有子串String[] split(String regExp)將調用字符串分解成幾個部分,并返回包含結果的數組。每一部分都由regExp傳遞的正則表達式進行界定String[] split(String regExp,int max)將調用字符串分解成幾個部分,并返回包含結果的數組。每一部分都由regExp傳遞的正則表達式進行界定。max指定分解的塊數。如果max是 負數,就完全分解調用字符串。否則,如果max包含非零值,那么結果數組中的最后一個元素是調用字符串的剩余部分。如果max是0,就完全分解調用字符串,但是不會包含后跟的空字符串CharSequence subSequence(int startIndex,int stopIndex)返回調用字符串的子串,從startIndex索引位置開始,并在stopIndex索引位置結束。該方法是CharSequence接口所需要的,String類實現了CharSequence接口
? ?注意這些方法中的多個都使用正則表達式進行工作。?
1.12 StringBuffer類?
? ?StringBuffer支持可修改的字符串。我們知道,String表示長度固定、不可修改的字符序列。與之相對應,StringBuffer表示可增長、可寫入的字符序列。StringBuffer允許在中間插入字符和子串,或者在末尾追加字符和子串。StringBuffer能夠自動增長,從而為這類添加操作準備空間,并且通常預先分配比實際需要更多的字符空間,以允許空間增長。?
1.12.1 StringBuffer類的構造函數?
? ?StringBuffer類定義了以下4個構造函數:?
StringBuffer()
StringBuffer(int size)
StringBuffer(String str)
StringBuffer(CharSequence chars)
?
? ?默認構造函數(沒有參數的那個)預留16個字符的空間,不需要再分配。第2個版本接收一個顯式設置緩沖區大小的整型參數。第3個版本接收一個設置StringBuffer對象初始化內容的String參數,并額外預留16個字符的空間,不需要再分配。如果沒有要求特定的緩沖區長度,StringBuffer會為16個附加字符分配空間,因為再次分配空間是很耗時的操作。此外,頻繁分配空間會產生內存碎片。通過為一部分額外字符分配空間,StringBuffer減少了再次分配空間的次數。第4個構造函數創建包含字符序列的對象,并額外預留16個字符的空間,包含的字符序列是由chars指定的。?
1.12.2 length() 與 capacity()?
? ?通過length()方法可以獲得StringBuffer對象的當前長度,而通過capacity()方法可以獲得已分配的容量。這兩個方法的一般形式如下:?
int length()
int capacity()
?
? ?下面是一個例子:?
//StringBuffer length vs capacity
class StringBufferDemo {
? public static void main(String[] args) {
? ? ? ?StringBuffer sb = new StringBuffer("Hello");
? ? ? ?System.out.println("buffer = "+sb);
? ? ? ?System.out.println("length = "+sb.length());
? ? ? ?System.out.println("capacity = "+sb.capacity());
? ? ? ?/**
? ? ? ? * 輸出:
? ? ? ? * buffer = Hello
? ? ? ? * length = 5
? ? ? ? * capacity = 21
? ? ? ? */
? ?}
}
?
? ?因為sb在創建時是使用字符串"Hello"初始化的,所以它的長度是5。因為自動添加了16個附加字符的空間,所以它的容量是21。?
1.12.3 ensureCapacity()?
? ?在創建了StringBuffer對象后,如果希望為特定數量的字符預先分配空間,可以使用ensureCapacity()方法設置緩沖區的大小。如果事先知道將要向StringBuffer對象追加大量的小字符串,這個方法是有用的。ensureCapacity()方法的一般形式為:?
void ensureCapacity(int minCapacity)
?
? ?其中,minCapacity指定了緩沖區的最小尺寸(處于效率方面的考慮,可能會分配比minCapacity更大的緩存區)。?
1.12.4 setLength()?
? ?可以使用setLength()方法設置StringBuffer中字符串的長度,一般形式為:?
void setLength(int len)
?
? ?其中,len指定字符串的長度,值必須非負。? ? 當增加字符串的大小時,會向末尾添加null字符。如果調用setLength()方法時,使用的值小于length()方法返回的當前值,那么超出新長度的字符將丟失。?
1.12.5 charAt() 與 setCharAt()?
? ?通過charAt()方法可以從StringBuffer獲取單個字符的值,使用setCharAt()方法可以設置StringBuffer對象中某個字符的值。這兩個方法的一般形式如下所示:?
char charAt(int where)
void setCharAt(int where,char ch)
?
? ?對于charAt()方法,where指定了將要獲取字符的索引。對于setCharAt()方法,where指定了將要設置字符的索引,ch指定了字符的新值。對于這兩個方法,where必須是非負的,并且不能超出字符串結尾的位置。下一節中的setCharAtDemo示例程序使用setLength()方法縮短了一個StringBuffer對象。? ? 下面的例子演示了charAt()和setCharAt()方法:?
//Demonstrate charAt() and setCharAt()
class setCharAtDemo {
? public static void main(String[] args) {
? ? ? StringBuffer sb = new StringBuffer("Hello");
? ? ? System.out.println("buffer before = "+sb);
? ? ? System.out.println("charAt(1) before = "+sb.charAt(1));
? ? ? sb.setCharAt(1,'i');
? ? ? System.out.println("setCharAt after = "+sb);
? ? ? sb.setLength(2);
? ? ? System.out.println("buffer after = "+sb);
? ? ? System.out.println("CharAt(1) after = "+sb.charAt(1));
? ? ? /**
? ? ? ?* 輸出:
? ? ? ?* buffer before = Hello
? ? ? ?* charAt(1) before = e
? ? ? ?* setCharAt after = Hillo
? ? ? ?* buffer after = Hi
? ? ? ?* CharAt(1) after = i
? ? ? ?*/
? }
}
?
1.12.6 getChars()?
? ?可以使用getChars()方法將StringBuffer對象的子串復制到數組中,一般形式為:?
void getChars(int sourceStart,int sourceEnd,char target[],int targetStart)
?
? ?其中,sourceStart指定了子串開始位置的索引,sourceEnd指定子串結束位置的最后一個位置的索引。這意味著子串將包含索引位置從sourceStart到sourceEnd-1之間的字符。接收字符的數組是由target指定的。targetStart指定了在target中開始復制子串的位置索引。用getChars()方法是一定要謹慎,確保target足以容納子串中的字符。?
1.12.7 append()?
? ?append()方法將各種其他類型數據的字符串表示形式連接到調用StringBuffer對象的末尾。該方法有一些重載版本,下面是其中的幾個:?
StringBuffer append(String str)
StringBuffer append(int num)
StringBuffer append(Object obj)
?
? ?通常調用String.valueOf()來獲取每個參數的字符串表示形式,結果將被添加到當前StringBuffer對象的末尾。緩沖區本身被各種版本的append()方法返回,從而可以將一系列調用連接起來,如下面的例子所示:?
//Demonstrate append().
class appendDemo {
? public static void main(String[] args) {
? ? ? ?String s;
? ? ? ?int a = 42;
? ? ? ?StringBuffer sb = new StringBuffer(40);
? ? ? ?s= sb.append("a = ").append(a).append("!").toString();
? ? ? ?System.out.println(s);
? ? ? ?/**
? ? ? ? * 輸出:
? ? ? ? * a = 42!
? ? ? ? */
? ?}
}
?
1.12.8 insert()?
? ?insert()方法將一個字符串插入到另一個字符串中。Java對該方法進行了重載,以接收所有基本類型以及String、Object和CharSequence類型的值。與append()類似,該方法獲取參數值的字符串表示形式,然后將字符串插入到調用StringBuffer對象中。下面是其中的幾種重載形式:?
StringBuffer insert(int index,String str)
StringBuffer insert(int index,char ch)
StringBuffer insert(int index,Object obj)
?
? ?其中,index指定了字符串插入到調用StringBuffer對象的位置索引。? ? 下面的示例程序將"like"插入到"I"和"Java"之間:?
//Demonstrate insert()
class insertDemo {
? public static void main(String[] args) {
? ? ? ?StringBuffer sb = new StringBuffer("I Java!");
? ? ? ?sb.insert(2,"like ");
? ? ? ?System.out.println(sb);
? ? ? ?/**
? ? ? ? * 輸出:
? ? ? ? * I like Java!
? ? ? ? */
? ?}
}
?
1.12.9 reverse()?
? ?可以使用reverse()方法顛倒StringBuffer對象中的字符,如下所示:?
StringBuffer reverse()
?
? ?該方法返回對象的反轉形式。下面的程序演示了reverse()方法:?
//Using reverse() to reverse a StringBuffer
class ReverseDemo {
? public static void main(String[] args) {
? ? ? ?StringBuffer s = new StringBuffer("abcdef");
? ? ? ?System.out.println(s);
? ? ? ?s.reverse();
? ? ? ?System.out.println(s);
? ? ? ?/**
? ? ? ? * 輸出:
? ? ? ? *abcdef
? ? ? ? *fedcba
? ? ? ? */
? ?}
}
?
1.12.10 delete() 與 deleteCharAt()?
? ?使用delete()和deleteCharAt()方法可以刪除StringBuffer對象中的字符。寫方法如下所示:?
StringBuffer delete(int startIndex,int endIndex)
StringBuffer deleteCharAt(int loc)
?
? ?delete()方法從調用對象刪除一連串字符。其中,startIndex指定第一個刪除字符的位置索引,endIndex指定要刪除的最后一個字符之后的下一個字符的位置索引。因此,結果是刪除索引位置從startIndex到endIndex-1之間的子串。刪除字符串后的StringBuffer對象作為結果返回。? ? deleteCharAt()方法刪除由loc指定的索引位置的字符,返回刪除字符后的StringBuffer對象。? ? 下面是演示delete()和deleteCharAt()方法的程序:?
//Demonstrate delete() and deleteCharAt()
class deleteDemo {
? public static void main(String[] args) {
? ? ? ?StringBuffer sb = new StringBuffer("This is a test.");
? ? ? ?sb.delete(4,7);
? ? ? ?System.out.println("After delete: "+sb);
? ? ? ?sb.deleteCharAt(0);
? ? ? ?System.out.println("After deleteCharAt: "+sb);
? ? ? ?/**
? ? ? ? * 輸出:
? ? ? ? * After delete: This a test.
? ? ? ? * After deleteCharAt: his a test.
? ? ? ? */
? ?}
}
?
1.12.11 replace()?
? ?通過調用replace()方法可以使用一個字符集替換StringBuffer對象中的另一個字符集。該方法的簽名如下所示:?
StringBuffer replace(int startIndex,int endIndex,String str)
?
? ?索引startIndex和endIndex指定了將被替換的子串,因此將替換startIndex和endIndex-1索引位置之間的子串。替換字符串是由str傳入的。替換后的StringBuffer對象作為結果返回。? ? 下面的程序演示了replace()方法:?
//Demonstrate replace()
class replaceDemo {
? public static void main(String[] args) {
? ? ? ?StringBuffer sb = new StringBuffer("This is a test.");
? ? ? ?sb.replace(5,7,"was");
? ? ? ?System.out.println("After replace: "+sb);
? ? ? ?/**
? ? ? ? * 輸出:
? ? ? ? * After replace: This was a test.
? ? ? ? */
? ?}
}
?
1.12.12 substring()?
? ?通過調用substring()方法可以獲得StringBuffer對象的一部分。該方法有以下兩種重載形式:?
String substring(int startIndex)
String substring(int startIndex,int endIndex)
?
? ?第一種形式返回從索引位置startIndex開始到調用StringBuffer對象末尾之間的子串,第二種形式返回startIndex和endIndex-1索引位置之間的子串。這些方法的工作方式與前面介紹的String類的對應方法類似。?
1.12.13 其他StringBuffer方法?
? ?除了剛才介紹的方法外,StringBuffer還提供了其他一些方法,如下表所示:?
?
?StringBuffer的其他一些方法
?
方法描述StringBuffer appendCodePoint(int ch)在調用對象的末尾添加一個Unicode代碼點,返回對調用對象的引用int codePointAt(int i)返回由i指定的位置的Unicode代碼點int codePointBefore(int i)返回由i指定的位置之前位置的Unicode代碼點int codePointCount(int start,int end)返回調用對象在位置start和end-1之間代碼點的數量int indexOf(String str)查找str在調用StringBuffer對象中的第一次出現時的位置索引,并返回索引。如果沒有找到,就返回-1int indexOf(String str,int startIndex)從startIndex位置索引開始查找查找str在StringBuffer對象中第一次出現時的位置索引,并返回索引。如果沒有找到,就返回-1int lastIndexOf(String str)查找str在調用StringBuffer對象中最后一次出現時的位置索引,并返回該索引。如果沒有找到,就返回-1int lastIndexOf(String str,int startIndex)從位置索引startIndex開始查找str在StringBuffer對象中最后一次出現時的位置索引,并返回該索引。如果沒有找到,就返回-1int offsetByCodePoints(int start,int num)返回調用字符串中超過start所指定索引位置num個代碼點的索引CharSequence subSequence(int startIndex,int stopIndex)返回調用字符串的一個子串,從位置索引startIndex開始,到stopIndex位置索引結束。這個方法是CharSequence接口所需要的,StringBuffer實現了該接口void trimToSize()要求為調用對象減小字符緩存對的大小,以更適合當前內容
? ?下面的程序演示了indexOf()方法和lastIndexOf()方法:?
//下面的程序演示了indexOf()方法和lastIndexOf()方法:
class IndexOfDemo {
? public static void main(String[] args) {
? ? ? ?StringBuffer sb = new StringBuffer("one two one");
? ? ? ?int i;
? ? ? ?i = sb.indexOf("one");
? ? ? ?System.out.println("First index: "+i);
? ? ? ?i = sb.lastIndexOf("one");
? ? ? ?System.out.println("Last index: "+i);
? ? ? ?/**
? ? ? ? * 輸出:
? ? ? ? * First index: 0
? ? ? ? * Last index: 8
? ? ? ? */
? ?}
}
?
1.13 StringBuilder類?
? ?StringBuilder類是由JDK5引入的,以增強Java的字符串處理能力。StringBuilder與StringBuffer類似,只有一個重要的區別:StringBuilder不是同步的,這意味著它不是線程安全的。StringBuilder的優勢在于能得到更高的性能。但是,如果可以修改的字符串將被多個線程修改,并且沒有其他同步措施的話,就必須使用StringBuffer,而不能使用StringBuilder。