3.字符串【Java溫故系列】

參考自–《Java技術核心卷1》

字符串

從概念上看,Java字符串就是Unicode字符序列。

Java沒有內置的字符串類型,而是在標準Java類庫中提供了一個預定義類,String.每個用雙引號括起來的字符串都是String類的一個實例:

String e = "";   //空字符串
String s = "String";

1 子串

String類的substring方法可以從一個較大的字符串提取出一個子串:

String s = "Hello";
String sz = s.substring(0,3);   //sz = "Hel"

創建了一個由字符"Hel"組成的字符串。

substring方法的第二個參數是不想複製的第一個位置。

上例中要複製的字符爲0、1、2(從0~2,包括0和2)位置上的字符,直到3爲止,但不包含3.

substring的工作方式有一個優點:容易計算子串的長度。字符串s.substring(a,b)的長度即爲b-a.


2 拼接

Java允許使用+號連接(拼接)兩個字符串。如:

String s1 = "Hello";
String s2 = " World";
String s = s1 + s2; //s的值爲  "Hello World"

當將一個字符串與一個非字符串的值進行拼接時,後者被轉換成字符串。

如果需要把多個字符串放到一起,用一個定界符分隔,可以使用靜態join方法:

String all = String.join("/","S","M","L"); // all 等於 "S/M/L"(/可爲其他符號)

3 不可變字符串

String類沒有提供可用於修改字符串的方法,由於不能修改Java字符串中的字符,所以Java文檔中將String類對象稱爲不可變字符串

如果要修改字符串,只能“拆”“接”進行:如"Hello"修改成"Help"

String s1 = "Hello";
String s2 = s1.substring(0,3)+"p"; // s2 等於 "Help"

如同數字3永遠是數字3一樣,字符串"Hello"永遠包含字符H,e,l,l,o的代碼單元序列,而不能修改其中的任何一個字符。當然,可以修改字符串變量,讓它引用另外一個新的字符串。

不可變字符串有一個優點:編譯器可以讓字符串共享

爲了弄清具體的工作方式,可以想象將各種字符串存放在公共的存儲池中。字符串變量指向存儲池中相應的位置。如果複製一個字符串變量 , 原始字符串與複製的字符串共享相同的字符。修改字符串變量即使它指向新的字符串。

由於Java具有垃圾回收機制,不存在內存遺漏問題。


4 檢測字符串是否相等

可以使用equals方法檢測兩個字符串是否相等。對於表達式:

s.equals(t);

如果字符串s與字符串t相等,則返回true;否則,返回false。s與t可以是字符串變量,也可以是字符串常量

要想檢測兩個字符串是否相等,而不區分大小寫,可以使用equalsIgnoreCase方法:

"Hello".equalsIgnoreCase("hello"); //true

:一定不要使用 == 運算符檢測兩個字符是否相等!

這個運算符只能夠確定兩個字符串是否放置在同一個位置上。當然,如果字符串放置在同一個位置上,它們必然相等。但是,完全有可能將內容相同的多個字符串的拷貝放置在不同的位置上。

如果虛擬機始終將相同的字符串共享,就可以使用運算符檢測是否相等。但實際上只有字符串常量是共享的,而+或substring等操作產生的結果並不是共享的。因此,千萬不要使用運算符測試字符串的相等性,以免在程序中出現糟糕的bug。從表面上看,這種bug很像隨機產生的間歇性錯誤。


5 空串和Null串

空串""是長度爲0的字符串。可以這樣判斷一個字符串是否爲空:

if(str.length()==0)

if(str.equals(""))

空串是一個Java對象,有自己的串長度(0)和內容(空)。不過String變量還可以存放一個特殊的值,名爲null,這表示目前沒有任何對象與該變量關聯。

要檢查一個字符串是否爲null,可以這樣判斷:

if(str == null)

有時需要檢查一個字符串既不是null也不爲空串:

if(str != null && str.length() != 0)

首先要檢查str不爲null(如果在一個null值上調用方法,會出現錯誤)。


6 碼點與代碼單元

Java字符串由char值序列組成。char數據類型是一個採用UTF-16編碼表示的Unicode碼點的代碼單元。大多數的常用的Unicode字符使用一個代碼單元就可以表示,而輔助字符需要一對代碼單元表示。

length方法返回的即爲採用UTF-16編碼表示的給定字符串所需要的代碼單元數量。

String s = "Hello";
int n = s.length(); // n 等於 5

要想得到實際的長度,即碼點數量,可以調用:

int nCount = s.codePointCount(0,s.length());

調用s.charAt(n)將返回字符串位置n的代碼單元,n介於0~s.length()-1之間。如:

char first = s.charAt(0);  // first爲s字符串的第一個字符,即'H'

要想得到第i個碼點:

int index = s.offsetByCodePoints(0,i);
int cp = s.codePointAt(index);

:如果要遍歷一個字符串,並依次查看每一個碼點,可使用codePoints方法,它會生成一個int值的“流”,每一個int值對應一個碼點。可以把它轉換爲一個數組,再完成遍歷:

int[] codePoints = s.codePoints().toArray();

反之,要把一個碼點數組轉換爲一個字符串,可以使用構造函數:

String str = new String(codePoints,0,codePoints.length);

7 String API

Java中的String類包含了50多個方法。

  • boolean startWith(String pre) 以 pre 開頭
  • boolean endWith(String end) 以 end 結尾
  • int indexOf(String str) 返回與字符串str匹配的第一個子串的開始位置,如果不存在,返回-1
  • int indexOf(String str,int fromIndex) 從fromIndex開始計算,返回與字符串str匹配的第一個子串的開始位置,如果不存在,返回-1
  • int lastIndexOf(String str) 返回與字符串str匹配的最後一個子串的開始位置,這個位置從原始串尾開始計算;同樣也可以有開始計算位置的參數fromIndex。
  • String replace(CharSequence oldstring,CharSequence newstring) 返回一個新的字符串。這個字符串用newstring代替原始字符串中的所有oldstring.可以用String或StringBuilder對象作爲參數
  • String toLowerCase() 返回一個新的字符串(將原始字符串中的大寫字母改爲小寫)
  • String toUpperCase() 返回一個新的字符串(將原始字符串中的小寫字母改爲大寫)
  • String trim() 返回一個新的字符串。這個字符串刪除了原始字符串頭部和尾部的空格

在API註釋中,有一些CharSequence類型的參數。這是一種接口類型,所有字符串都屬於這個接口。CharSequence形參,完全可以傳入String類型的實參。


8 構建字符串

有些時候,需要由較短的字符串構建字符串,而採用字符串連接的方式達到此目的的效率比較低。每次連接字符串,都會構建一個新的String對象,既耗時,又耗內存。

使用StringBuilder類可以避免這個問題的發生。

如果需要用許多小段的字符串構建字符串,那麼應該按照下列步驟進行。

1.首先,構建一個空的字符串構建器:

StringBuilder builder = new StringBUilder();

2.當每次需要添加一部分內容時,就調用append方法:

builder.append(ch);  //ch表示一個字符
builder.append(str);  //str表示一個字符串

3.在需要構建字符串時調用toString方法,將可以得到一個String對象,其中包含了構建器中的字符序列:

String completedString = builder.toString();

:在JDK5.0引入StringBuilder類。這個類的前身是StringBuffer,其效率稍有些低,但允許採用多線程的方式執行添加或刪除字符的操作。如果所有字符串在一個單線程中編輯,則應該使用StringBuilder替代它。

以下是StringBuilder類中的重要方法:

  • StringBuilder() 構建一個空的字符串構建器
  • int length() 返回構建器或緩衝器中的代碼單元數量
  • StringBuilder append(String str) 追加一個字符串並返回this
  • StringBuilder append(Char c) 追加一個代碼單元並返回this
  • void setCharAt(int i,Char c) 將第i個代碼單元設置爲c
  • StringBuilder insert(int offset,String str) 在offset位置插入一個字符串並返回this
  • StringBuilder insert(int offset,Char c) 在offset位置插入一個代碼單元並返回this
  • StringBuilder delete(int startIndex,int endIndex) 刪除偏移量從startIndex到endIndex-1的代碼單元並返回this
  • String toString() 返回一個與構建器或緩衝器內容相同的字符串
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章