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

你不太可能经常使用这种方法,但人们喜欢在面试中询问它。所以知道它总比不知道好。