
本文讲解如何正确分割符合规则的字符串为纯字母令牌,并先输出令牌总数、再逐行打印各令牌,重点解决输出顺序错位及首尾分隔符导致计数不准的问题。
本文讲解如何正确分割符合规则的字符串为纯字母令牌,并先输出令牌总数、再逐行打印各令牌,重点解决输出顺序错位及首尾分隔符导致计数不准的问题。
在处理如 He is a very very good boy, isn't he? 这类含标点与空格的字符串时,题目要求:仅将连续英文字母(a–z, A–Z)视为有效 token,忽略所有非字母字符(包括空格、逗号、问号、引号、下划线等),并按出现顺序输出——但必须先打印 token 总数,再逐行打印每个 token。
你当前代码的核心问题在于:
✅ 正确使用 split("[ !,?._'@]+") 切分字符串;
❌ 但遍历过程中边计数边打印,导致 tokenCount 被延后输出;
⚠️ 更隐蔽的问题是:若输入以分隔符开头(如 " Hello")或结尾(如 "Hi!"),split() 默认会产生空字符串元素(如 ["", "Hello"] 或 ["Hi", ""]),直接取 tokens.length 会高估数量。
✅ 推荐方案:预过滤 + 安全计数(简洁健壮)
最佳实践是先收集所有非空 token,再统一输出,既保证顺序,又规避空串干扰:
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String s = scan.nextLine();
// 使用正则分割,保留所有可能的空段
String[] candidates = s.split("[ !,?._'@]+");
// 过滤掉空字符串,只保留有效 token
List<string> tokens = new ArrayList();
for (String cand : candidates) {
if (!cand.isEmpty()) {
tokens.add(cand);
}
}
// 先输出总数
System.out.println(tokens.size());
// 再逐行输出每个 token
for (String token : tokens) {
System.out.println(token);
}
}
}</string>
? 关键细节说明
为什么不能直接用
tokens.length?String.split(regex)在字符串开头/结尾匹配分隔符时,会生成前置或后置空字符串。例如:s = "!Hello"→split("[!]+")→["", "Hello"]→length == 2(错误);
正确 token 数应为1,必须显式过滤isEmpty()。正则
[ !,?._'@]+的含义:
匹配一个或多个空格、感叹号、逗号、问号、英文句点、下划线、单引号或@符号,完全覆盖题目给定字符集[A-Za-z !,?._'@]中的非字母部分。性能与可读性平衡:
使用ArrayList存储有效 token 略增内存,但逻辑清晰、无边界风险,远优于手动处理首尾匹配或复杂正则前瞻/后顾断言,适合竞赛与工程场景。
✅ 验证示例
输入:
He is a very very good boy, isn't he?
执行流程:
-
split(...)得到["He","is","a","very","very","good","boy","","t","he"](注意isn't被'拆成"isn"和"t"); - 过滤空串后得 10 个非空字符串;
- 输出:先
10,再依次打印全部 token —— 完全匹配样例预期。
? 提示:若需进一步提升效率(如超长文本),可改用两次遍历(首次统计有效 token 数,二次打印),避免集合扩容;但对常规输入,本方案已足够高效且不易出错。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











