2.1 概述

本文将深入探讨 Java 中的一个基础类——StringTokenizer。这个工具类虽然简单,但在特定场景下处理字符串分割时特别实用。

2.2 StringTokenizer

StringTokenizer 的核心功能是将字符串拆分为多个标记(tokens)。

与功能更复杂的 StreamTokenizer 相比,StringTokenizer 的实现方式更为直接。它不会区分标识符、数字和引用字符串,也不识别或跳过注释。

分隔符(用于分隔标记的字符)可以在创建时指定,也可以在处理每个标记时动态设置。

2.3 使用 StringTokenizer

最典型的用法是根据指定分隔符拆分字符串。下面这个简单示例将字符串拆分后存入列表:

public List<String> getTokens(String str) {
    List<String> tokens = new ArrayList<>();
    StringTokenizer tokenizer = new StringTokenizer(str, ",");
    while (tokenizer.hasMoreElements()) {
        tokens.add(tokenizer.nextToken());
    }
    return tokens;
}

这段代码通过逗号分隔符拆分字符串,并在循环中将每个标记添加到 ArrayList。例如输入 "Welcome,to,baeldung.com" 会返回包含 "Welcome""to""baeldung.com" 的列表。

2.3.1 Java 8 风格实现

由于 StringTokenizer 实现了 Enumeration 接口,我们可以结合 Java 8 的 Stream API 更优雅地处理:

public List<String> getTokensWithCollection(String str) {
    return Collections.list(new StringTokenizer(str, ",")).stream()
      .map(token -> (String) token)
      .collect(Collectors.toList());
}

⚠️ 注意:Enumeration 返回的是 Object 类型,必须显式转换为 String(如果处理其他类型如 Integer/Float 需对应转换)。

2.3.2 构造器变体

StringTokenizer 提供三个构造器:

  • StringTokenizer(String str):默认使用 \t\n\r\f 作为分隔符
  • StringTokenizer(String str, String delim):指定分隔符
  • StringTokenizer(String str, String delim, boolean returnDelims):额外参数决定是否将分隔符作为标记返回

2.3.3 动态分隔符

通过重载的 nextToken() 方法可以动态调整分隔符:

tokens.add(tokenizer.nextToken("e"));

对字符串 "Hello,baeldung.com" 使用 e 作为分隔符会产生:

H
llo
ba
ldung.com

2.3.4 标记计数

使用 countTokens() 快速获取剩余标记数量:

int tokenLength = tokens.countTokens();

2.3.5 解析 CSV 文件

实际开发中常用 StringTokenizer 解析 CSV 文件:

public List<String> getTokensFromFile( String path , String delim ) {
    List<String> tokens = new ArrayList<>();
    String currLine = "";
    StringTokenizer tokenizer;
    try (BufferedReader br = new BufferedReader(
        new InputStreamReader(Application.class.getResourceAsStream( 
          "/" + path )))) {
        while (( currLine = br.readLine()) != null ) {
            tokenizer = new StringTokenizer( currLine , delim );
            while (tokenizer.hasMoreElements()) {
                tokens.add(tokenizer.nextToken());
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return tokens;
}

假设 CSV 文件内容:

1|IND|India
2|MY|Malaysia
3|AU|Australia

输出结果:

1
IND
India
2
MY
Malaysia
3
AU
Australia

2.3.6 单元测试

验证功能的测试用例:

public class TokenizerTest {

    private MyTokenizer myTokenizer = new MyTokenizer();
    private List<String> expectedTokensForString = Arrays.asList(
      "Welcome" , "to" , "baeldung.com" );
    private List<String> expectedTokensForFile = Arrays.asList(
      "1" , "IND" , "India" , 
      "2" , "MY" , "Malaysia" , 
      "3", "AU" , "Australia" );

    @Test
    public void givenString_thenGetListOfString() {
        String str = "Welcome,to,baeldung.com";
        List<String> actualTokens = myTokenizer.getTokens( str );
 
        assertEquals( expectedTokensForString, actualTokens );
    }

    @Test
    public void givenFile_thenGetListOfString() {
        List<String> actualTokens = myTokenizer.getTokensFromFile( 
          "data.csv", "|" );
 
        assertEquals( expectedTokensForFile , actualTokens );
    }
}

2.4 总结

StringTokenizer 虽然是 Java 早期的工具类,但在处理简单字符串分割场景时仍然高效直接。不过需要注意: ✅ 适合固定分隔符的简单场景 ❌ 不支持正则表达式(不如 String.split() 灵活) ⚠️ 线程不安全(多线程环境需额外处理)

在需要高性能处理大量结构化文本时(如日志解析),它仍然是个不错的选择。


原始标题:Quick Guide to the Java StringTokenizer | Baeldung