1.StringTokenizer

現在還有一些涉及使用字符串的常見場景。你如何將一個字符串分成幾個部分?做這件事有很多種方法。

split()方法

將字符串拆分為多個部分的第一種方法是使用split()方法。定義特殊分隔字符串的正則表達式必須作為參數傳遞。您將在Java 多線程任務中了解什麼是正則表達式。

例子:

代碼 結果
String str = "Good news everyone!";
String[] strings = str.split("ne");
System.out.println(Arrays.toString(strings));
結果將是一個包含三個字符串的數組:
["Good ", "ws everyo", "!"]

很簡單,但有時這種方法是多餘的。如果有很多定界符(例如,空格、換行符、製表符、句點),那麼您必須構造一個相當複雜的正則表達式。它很難閱讀,因此也很難修改。

StringTokenizer班級

Java 有一個特殊的類,它的全部工作就是將字符串拆分為子字符串。

此類不使用正則表達式:相反,您只需傳入一個由定界符組成的字符串。這種方法的優點是它不會一次將整個字符串分解成多個部分,而是一次從頭到尾移動一步。

該類有一個構造函數和兩個重要的方法。我們向構造函數傳遞一個我們拆分成多個部分的字符串,以及一個由一組定界字符組成的字符串。

方法 描述
String nextToken()
返回下一個子串
boolean hasMoreTokens()
檢查是否有更多的子字符串。

這個類在某種程度上讓人想起 Scanner 類,它也有nextLine()hasNextLine()方法。

您可以使用以下命令創建StringTokenizer對象:

StringTokenizer name = new StringTokenizer(string, delimiters);

string要分割的字符串在哪裡。anddelimiters是一個字符串,其中的每個字符都被視為分隔符。例子:

代碼 控制台輸出
String str = "Good news everyone!";

StringTokenizer tokenizer = new StringTokenizer(str,"ne");
while (tokenizer.hasMoreTokens())
{
   String token = tokenizer.nextToken();
   System.out.println(token);
}
Good 
ws 
v
ryo
!

請注意,作為第二個字符串傳遞給StringTokenizer構造函數的字符串中的每個字符都被視為分隔符。



2.String.format()方法和StringFormatter

String 類的另一個有趣的方法是format().

假設您有各種變量存儲數據。你如何在一行中將它們顯示在屏幕上?例如,我們有一些數據(左列)和所需的輸出(右列):

代碼 控制台輸出
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;
User = {name: Amigo, age: 12 years, friend: Diego, weight: 200 kg.}

您的代碼可能看起來像這樣:

程序代碼
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;

System.out.println("User = {name: " + name + ", age:" + age + " years, friend: " + friend+", weight: " + weight + " kg.}");

這樣的代碼可讀性不是很好。如果變量名更長,那麼代碼將變得更加困難:

程序代碼

class User {
    ......
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public List<String> getFriends() {
        return friends;
    }

    public ExtraInformation getExtraInformation() {
        return extraInformation;
    }
}

User user = new User();

System.out.println("User = {name: " + user.getName() + ", age:" + user.getAge() + " years, friend: " + user.getFriends().get(0) + ", weight: " + user.getExtraInformation().getWeight() + " kg.}");

不是很可讀,是嗎?

但這種情況在現實程序中是很常見的,所以我想告訴大家一種方法,可以把這段代碼寫得更簡單、更簡潔。

String.format

String 類有一個靜態format()方法:它允許您指定一種模式來將字符串與數據組合在一起。命令的一般外觀如下:

String name = String.format(pattern, parameters);

例子:

代碼 結果
String.format("Age=%d, Name=%s", age, name);
Age=12, Name=Amigo
String.format("Width=%d, Height=%d", width, height);
Width=20, Height=10
String.format("Fullname=%s", name);
Fullname=Diego

該方法的第一個參數是一個格式字符串,它包含所有需要的文本以及在您需要插入數據的地方format()稱為格式說明符(例如%d和)的特殊字符。%s

format()方法將這些%s%d格式說明符替換為參數列表中格式字符串後面的參數。如果我們想插入一個字符串,那麼我們寫%s. 如果我們想插入一個數字,那麼格式說明符是%d. 例子:

代碼 結果
String s = String.format("a=%d, b=%d, c=%d", 1, 4, 3);
s等於"a=1, b=4, c=3"

以下是可在格式字符串中使用的格式說明符的簡短列表:

說明符 意義
%s
String
%d
整數:byte, short, int,long
%f
實數:float,double
%b
boolean
%c
char
%t
Date
%%
%特點

這些說明符指示數據的類型,但也有指示數據順序的說明符。要通過其編號獲取參數(編號從一開始),您需要編寫“ ”而不是“ ”。例子:%1$d%d

代碼 結果
String s = String.format("a=%3$d, b=%2$d, c=%d", 11, 12, 13);
s等於"a=13, b=12, c=11"

%3$d將獲得第三個參數,%2$d將獲得第二個參數,並將%d獲得第一個參數。和格式說明符引用參數,而不管說明符%s如或%d%3$d%2$s



3.字符串池

StringPool在程序運行時,代碼中指定為字符串文字的每個字符串都存儲在稱為 的內存區域中。StringPool是一個存放字符串的特殊數組。其目的是優化字符串存儲:

首先,代碼中指定的字符串必須存儲在某個地方,對嗎?代碼由命令組成,但數據(尤其是大字符串)必須與代碼分開存儲在內存中。只有對字符串對象的引用才會出現在代碼中。

其次,所有相同的字符串文字必須僅在內存中存儲一次。這就是它的工作原理。當您的類代碼被 Java 機器加載時,所有字符串文字都會添加到StringPoolif 它們還不存在。如果它們已經存在,那麼我們只需使用StringPool.

因此,如果您將相同的文字分配給String代碼中的多個變量,那麼這些變量將包含相同的引用。文字將被添加到StringPool唯一一次。在所有其他情況下,代碼將獲得對已加載到StringPool.

以下是它的大致工作原理:

代碼 使用字符串池
String a = "Hello";
String b = "Hello";
String c = "Bye";
String[] pool = {"Hello", "Bye"};
a = pool[0];
b = pool[0];
c = pool[1];

這就是為什麼ab變量將存儲相同的引用。

intern()方法

最好的部分是您可以通過編程方式將任何字符串添加到StringPool. 為此,您只需調用String變量的intern()方法。

intern()如果該字符串StringPool不存在,該方法會將其添加到 中,並返回對 中字符串的引用StringPool

如果將兩個相同的字符串添加到StringPoolusingintern()方法中,則該方法返回相同的引用。這可用於通過引用比較字符串。例子:

代碼 筆記
String a = new String("Hello");
String b = new String("Hello");
System.out.println(a == b);


false
String a = new String("Hello");
String b = new String("Hello");

String t1 = a.intern();
String t2 = b.intern();
System.out.println(a == b);
System.out.println(t1 == t2);





false
true

你不太可能經常使用這種方法,但人們喜歡在面試中詢問它。所以知道它總比不知道好。