scanner.next(pattern) 跳过不匹配token,返回首个完全匹配的token,无匹配时抛nosuchelementexception;需配合hasnext(pattern)预检实现安全读取。

Scanner.next(Pattern) 的作用不是“仅在匹配时才读取”,而是**跳过前面所有不匹配的内容,直到找到下一个能完全匹配该 Pattern 的 token,然后返回它**。它本身不会“条件性读取”或“静默失败”,而是在找不到匹配项时抛出 NoSuchElementException。
理解 next(Pattern) 的实际行为
Scanner 默认以空白(空格、制表符、换行等)为分隔符切分输入流,形成一个个“token”。next(Pattern) 会在这些 token 中顺序查找——第一个能被整个 Pattern 完全匹配的 token(即从头到尾都符合,不只前缀匹配),然后消费并返回它。
例如:
- 输入:
"abc 123 def456 789" - Pattern:
Pattern.compile("\d+") - 结果:
next()返回"123"(跳过"abc",匹配"123";"def456"不匹配,"789"虽然也匹配但排在后面,不会被本次调用返回)
实现“仅匹配时才读取”的安全方式
要避免异常、实现“有匹配才取,无匹配就跳过或忽略”,需结合 hasNext(Pattern) 预检:
- 先调用
scanner.hasNext(pattern)—— 返回true表示下一个 token 完全匹配该 Pattern - 只有返回
true时,才调用scanner.next(pattern)安全获取 - 否则可选择跳过(调用
scanner.next()消耗当前不匹配 token)、重试或退出
示例代码:
Scanner sc = new Scanner("hello 42 world -123 abc 99.5");
Pattern intPattern = Pattern.compile("-?\d+");
while (sc.hasNext()) {
if (sc.hasNext(intPattern)) {
String matched = sc.next(intPattern);
System.out.println("整数匹配: " + matched);
} else {
sc.next(); // 跳过不匹配的 token
}
}
注意边界:匹配的是 token,不是任意子串
next(Pattern) 不会在一个 token 内部搜索子串。比如输入 "abc123def"(中间无空格),整个就是一个 token;若 Pattern 是 \d+,它不会匹配出 "123",因为 "abc123def" 整体不满足 \d+。此时 hasNext(intPattern) 返回 false。
如需子串提取,应改用 findInLine() 或手动用 Pattern.matcher(scanner.nextLine()).find()。
常见误用与替代建议
- ❌ 用
next(Pattern)解析带小数点的数字?
→"3.14"不匹配\d+;改用"-?\d+\.?\d*"并注意浮点精度问题,或直接用nextDouble() - ❌ 希望跳过注释或特定前缀?
→ Scanner 的 delimiter 和 Pattern 匹配机制不支持“跳过但不消费”逻辑;考虑预处理输入流或切换为正则 matcher 方式 - ✅ 更灵活的方案:用
scanner.useDelimiter("\s+")统一分隔,再对每个next()结果手动pattern.matcher(str).matches()判断
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











