如何在 Java 中按多种分隔符(空格、逗号、括号)安全拆分字符串并提取关键词

本文介绍一种基于正则表达式的高效方法,用于从混合结构字符串(如含空格分隔词、括号内逗号分隔项)中统一提取所有语义单元,并存入 list;适用于 apple、apple orange、apple (banana, grape) 等多场景。

在实际开发中,我们常需解析结构松散但有规律的用户输入或配置字符串,例如 "Apple Orange (Banana Ice Cream, Grape)"。这类字符串包含两类语义单元:

  • 括号外部分:以空格连接的连续词组(视为一个整体,如 "Apple Orange");
  • 括号内部分:以逗号分隔的多项(支持含空格的短语,如 "Banana Ice Cream"),且括号本身不参与语义。

为统一提取所有有效项(忽略括号、逗号、空格等分隔符),推荐使用正则表达式进行一次性分割。核心思路是:将所有可能的“分隔边界”抽象为一个正则模式——即:

  • 逗号(前后可带任意空白):\s*,\s*
  • 左括号(后接任意空白):\s*\(
  • 右括号(前接任意空白):\s*\)

合并后得到完整分隔符正则:

String DELIMITER = "\\s*,\\s*|\\s*\\(|\\s*\\)";

⚠️ 注意:该方案不校验括号配对或嵌套(如 (A, (B,C)) 会错误切分),仅适用于单层括号、格式基本正确的输入。若需严格语法校验,应改用状态机或专用解析器。

以下是完整可运行示例:

import java.util.*;

public class StringSplitter {
    private static final String DELIMITER = "\\s*,\\s*|\\s*\\(|\\s*\\)";

    public static List extractTerms(String input) {
        if (input == null || input.trim().isEmpty()) {
            return Collections.emptyList();
        }
        // 分割后过滤空字符串(避免因首尾空格/多余分隔符产生空项)
        return Arrays.stream(input.split(DELIMITER))
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .toList(); // Java 16+;如用低版本,替换为 .collect(Collectors.toList())
   

} public static void main(String[] args) { String k1 = "Apple"; String k2 = "Apple Orange"; String k3 = "Apple (Banana, Orange, Grape)"; String k4 = "Apple Orange (Banana, Grape)"; String k5 = "Apple Orange (Banana Ice cream, Grape)"; System.out.println(extractTerms(k1)); // [Apple] System.out.println(extractTerms(k2)); // [Apple Orange] System.out.println(extractTerms(k3)); // [Apple, Banana, Orange, Grape] System.out.println(extractTerms(k4)); // [Apple Orange, Banana, Grape] System.out.println(extractTerms(k5)); // [Apple Orange, Banana Ice cream, Grape] } }

✅ 输出完全符合预期:括号外空格连接项保留为整体,括号内逗号分隔项独立成项,且各部分内部空格(如 "Banana Ice cream")被完整保留。

关键注意事项

  • 正则中的 \\s* 确保兼容空格扰动(如 "Apple( Banana ,Grape )" 仍能正确解析);
  • .trim() 和 .filter(s -> !s.isEmpty()) 是健壮性必需步骤,防止因输入格式异常引入空字符串;
  • 若需兼容 Java 8,将 .toList() 替换为 .collect(Collectors.toList()) 即可;
  • 对于含转义字符、嵌套括号或更复杂语法的场景,建议升级为 ANTLR 或手写简易递归下降解析器。

该方案简洁、高效、可读性强,是处理此类“轻量级结构化文本”的首选实践。