1. 概述

在Java中,String 可以视为多个子串的连接。通常,我们使用空格作为分隔符来构建和存储一个包含多个子串的单一字符串。

本教程将**介绍如何通过空格字符(如空格、制表符或换行符)分割String**。

2. String 示例

首先,我们需要创建一些String示例,用作按空格分割的输入。我们先定义一些空格字符作为String常量,以便于方便地重用:

String SPACE = " ";
String TAB = "    ";
String NEW_LINE = "\n";

接下来,我们将这些作为分隔符,定义包含不同水果名称的String示例:

String FRUITS_TAB_SEPARATED = "Apple" + TAB + "Banana" + TAB + "Mango" + TAB + "Orange";
String FRUITS_SPACE_SEPARATED = "Apple" + SPACE + "Banana" + SPACE + "Mango" + SPACE + "Orange";
String FRUITS_NEWLINE_SEPARATED = "Apple" + NEW_LINE + "Banana" + NEW_LINE + "Mango" + NEW_LINE + "Orange";

最后,我们编写一个名为verifySplit()的方法,用于验证通过空格字符分割这些字符串的预期结果:

private void verifySplit(String[] fruitArray) {
    assertEquals(4, fruitArray.length);
    assertEquals("Apple", fruitArray[0]);
    assertEquals("Banana", fruitArray[1]);
    assertEquals("Mango", fruitArray[2]);
    assertEquals("Orange", fruitArray[3]);
}

现在我们已经准备好了输入字符串,可以探索不同的分割策略并验证结果。

3. 使用分隔符正则表达式分割

String类的split()方法是标准的字符串分割方式。它接受一个分隔符正则表达式,并将字符串分割成一个String数组:

String[] split(String regex);

首先,让我们使用单个空格字符分割FRUITS_SPACE_SEPARATED字符串:

@Test
public void givenSpaceSeparatedString_whenSplitUsingSpace_shouldGetExpectedResult() {
    String fruits = FRUITS_SPACE_SEPARATED;
    String[] fruitArray = fruits.split(SPACE);
    verifySplit(fruitArray);
}

同样,我们可以使用TABNEW_LINE作为分隔符正则表达式,分别分割FRUITS_TAB_SEPARATEDFRUITS_NEWLINE_SEPARATED

接下来,尝试使用更通用的正则表达式来匹配空格、制表符和换行符,并用同一正则表达式分割所有字符串样本

@Test
public void givenWhiteSpaceSeparatedString_whenSplitUsingWhiteSpaceRegex_shouldGetExpectedResult() {
    String whitespaceRegex = SPACE + "|" + TAB + "|" + NEW_LINE;
    String[] allSamples = new String[] { FRUITS_SPACE_SEPARATED, FRUITS_TAB_SEPARATED, FRUITS_NEWLINE_SEPARATED };
    for (String fruits : allSamples) {
        String[] fruitArray = fruits.split(whitespaceRegex);
        verifySplit(fruitArray);
    }
}

到目前为止,看起来一切正常!

最后,我们可以通过使用**代表所有类型空格字符的元字符\s**来简化我们的方法:

@Test
public void givenNewlineSeparatedString_whenSplitUsingWhiteSpaceMetaChar_shouldGetExpectedResult() {
    String whitespaceMetaChar = "\\s";
    String[] allSamples = new String[] { FRUITS_SPACE_SEPARATED, FRUITS_TAB_SEPARATED, FRUITS_NEWLINE_SEPARATED };
    for (String fruits : allSamples) {
        String[] fruitArray = fruits.split(whitespaceMetaChar);
        verifySplit(fruitArray);
    }
}

值得注意的是,使用\s元字符比自定义空格正则表达式更为方便且可靠。如果输入字符串可能有多个空格字符作为分隔符,我们可以使用\\s+而不是\\s,而无需更改其余代码。

4. 使用StringTokenizer分割

按空格分割字符串是如此常见的用例,以至于许多Java库提供了接口来实现这一功能,而无需明确指定分隔符。在这个部分,我们将学习如何使用StringTokenizer来解决这个问题:

@Test
public void givenSpaceSeparatedString_whenSplitUsingStringTokenizer_shouldGetExpectedResult() {
    String fruits = FRUITS_SPACE_SEPARATED;
    StringTokenizer tokenizer = new StringTokenizer(fruits);
    String[] fruitArray = new String[tokenizer.countTokens()];
    int index = 0;
    while (tokenizer.hasMoreTokens()) {
        fruitArray[index++] = tokenizer.nextToken();
    }
    verifySplit(fruitArray);
}

我们可以看到,我们没有提供任何分隔符,因为StringTokenizer默认使用空格作为分隔符。此外,代码遵循了迭代器设计模式,其中hasMoreTokens()方法决定循环终止条件,而nextToken()给出下一个分割值

另外,我们使用countTokens()方法预估了分割的数量。但如果只想顺序获取每个分割后的结果,而不等待整个过程完成,这就不需要。一般来说,当输入字符串较长并且希望立即获取下一个分割结果时,应采用这种方法

5. 使用Apache Commons分割

org.apache.commons.lang3包中的StringUtils类提供了一个名为split()的实用方法,用于分割String。与StringTokenizer类类似,它也使用空格作为默认的分隔符来分割字符串:

public static String[] split(String str);

首先,在项目的pom.xml文件中添加commons-lang3依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
</dependency>

然后,让我们看看它的实际操作,分割String示例:

@Test
public void givenWhiteSpaceSeparatedString_whenSplitUsingStringUtils_shouldGetExpectedResult() {
    String[] allSamples = new String[] { FRUITS_SPACE_SEPARATED, FRUITS_TAB_SEPARATED, FRUITS_NEWLINE_SEPARATED };
    for (String fruits : allSamples) {
        String[] fruitArray = StringUtils.split(fruits);
        verifySplit(fruitArray);
    }
}

使用StringUtils.split()方法的一个优点是,调用者无需显式进行null检查,因为split()方法能优雅地处理这种情况。让我们继续看这个例子:

@Test
public void givenNullString_whenSplitUsingStringUtils_shouldReturnNull() {
    String fruits = null;
    String[] fruitArray = StringUtils.split(fruits);
    assertNull(fruitArray);
}

正如预期,对于null输入,方法返回null

6. 总结

在这篇教程中,我们学习了多种通过空格分割String的方法。同时,我们也注意到了一些策略的优势和推荐的最佳实践。

如往常一样,本教程的完整源代码可在GitHub上找到。