当前位置: 首页 > news >正文

【基础语法】Java Scanner hasNext() 和 hasNextLine() 的区别

OJ在线编程常见输入输出练习中默认模板

import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextInt()) { // 注意 while 处理多个 caseint a = in.nextInt();int b = in.nextInt();System.out.println(a + b);}}
}

API源码解析

JDK 8

Java.util.Scanner Structure
Java.util.Scanner 类结构

hasNext

功能:判断是否还有下一个值,通过检查缓冲区数据和标记(token)实现。

关键方法:

  1. 循环检查输入:使用一个while循环来不断检查输入源是否关闭(sourceClosed变量)。在循环内部:

    • 如果当前缓冲区中有可用的标记(通过hasTokenInBuffer()方法检查),则通过revertState(true)恢复状态并返回true
    • 如果没有可用的标记,则调用readInput()方法从输入源中读取更多的输入到缓冲区中。
  2. 处理循环结束后的状态:如果循环因为sourceClosedtrue而结束(即输入源已经关闭),则再次检查缓冲区中是否有可用的标记。

Note:有三种重载。

    /*** Returns true if this scanner has another token in its input.* This method may block while waiting for input to scan.* The scanner does not advance past any input.** @return true if and only if this scanner has another token* @throws IllegalStateException if this scanner is closed* @see java.util.Iterator*/public boolean hasNext() {ensureOpen();saveState();while (!sourceClosed) {    //sourceClosed 跟踪输入源是否已经关闭if (hasTokenInBuffer())return revertState(true);readInput();}boolean result = hasTokenInBuffer();return revertState(result);}/*** Returns true if the next complete token matches the specified pattern.* A complete token is prefixed and postfixed by input that matches* the delimiter pattern. This method may block while waiting for input.* The scanner does not advance past any input.** @param pattern the pattern to scan for* @return true if and only if this scanner has another token matching*         the specified pattern* @throws IllegalStateException if this scanner is closed*/public boolean hasNext(Pattern pattern) {ensureOpen();if (pattern == null)throw new NullPointerException();hasNextPattern = null;saveState();while (true) {if (getCompleteTokenInBuffer(pattern) != null) {matchValid = true;cacheResult();return revertState(true);}if (needInput)readInput();elsereturn revertState(false);}}/*** Returns true if the next token matches the pattern constructed from the* specified string. The scanner does not advance past any input.** <p> An invocation of this method of the form <tt>hasNext(pattern)</tt>* behaves in exactly the same way as the invocation* <tt>hasNext(Pattern.compile(pattern))</tt>.** @param pattern a string specifying the pattern to scan* @return true if and only if this scanner has another token matching*         the specified pattern* @throws IllegalStateException if this scanner is closed*/public boolean hasNext(String pattern)  {return hasNext(patternCache.forName(pattern));}

hasNextLine

功能:判断是否还有下一行。利用正则表达式匹配来查找行分隔符,并根据查找结果决定是否返回true。

方法实现:

  1. 保存当前状态:通过saveState()方法保存当前扫描器的状态,以便在方法结束时可以恢复到这个状态。这是为了确保方法调用前后扫描器的状态不变。

  2. 查找下一行:使用findWithinHorizon(linePattern(), 0)方法尝试在输入中查找符合行模式的字符串。这里linePattern()返回用于匹配行模式的正则表达式,0表示没有超时限制。

  3. 处理匹配结果

    • 如果找到了匹配项(即result不为null),则进一步处理:
      • 通过this.match()获取匹配结果(MatchResult)。
      • 提取出匹配到的行分隔符(lineSep)。
      • 如果存在行分隔符,则从结果中去除行分隔符部分,并缓存处理后的结果。
      • 如果不存在行分隔符,则直接缓存结果(此时可能是读取到了输入的末尾,但没有明确的行分隔符)。
    • 如果没有找到匹配项,则不缓存任何结果。
  4. 恢复之前的状态:通过revertState()方法恢复扫描器到调用saveState()时的状态。

  5. 返回结果:如果找到了下一行的匹配项(即result不为null),则返回true;否则返回false

Note:只有一种类型的接口,无参。

    /*** Returns true if there is another line in the input of this scanner.* This method may block while waiting for input. The scanner does not* advance past any input.** @return true if and only if this scanner has another line of input* @throws IllegalStateException if this scanner is closed*/public boolean hasNextLine() {saveState();String result = findWithinHorizon(linePattern(), 0);if (result != null) {MatchResult mr = this.match();String lineSep = mr.group(1);if (lineSep != null) {result = result.substring(0, result.length() -lineSep.length());cacheResult(result);} else {cacheResult();}}revertState();return (result != null);}

结论用法

采用 hasXxxx 判断时,后面读取输入也要使用匹配的 nextXxxx 。

比如先用 hasNextLine 对控制台输入判断时,那么后续需要使用 nextLine 来处理输入。

  • hasNext 
  • hasNextXxxx 判断下一个xxx类型
  • hasNextLine 判断是否有下一行

关于 token 说明

上面有提到判断场景的token标记,那么这是什么概念和实际作用呢?

下一个标记可以先粗略理解为下一个数据(但数据类型未知)。

在Java的Scanner类中,术语“标记”(token)通常指的是输入流中可以被识别并作为一个单元处理的字符串或字符序列Scanner类使用分隔符(如空格、制表符、换行符等)来区分不同的标记。例如,当你使用Scanner从控制台读取输入时,你可以通过空格、逗号或其他分隔符来分隔不同的标记。

Scanner 的使用案例

在Java输入控制台(即标准输入流,通常是键盘输入)中,Scanner类通过以下方式实现标记的识别:

1、创建Scanner对象:new并将其与标准输入流System.in关联起来。

Scanner scanner = new Scanner(System.in);

2、设置分隔符(可选):默认情况下,Scanner使用空白(空格、制表符、换行符等)作为分隔符。但是,你可以通过调用useDelimiter(String pattern)方法来设置自定义的分隔符。

例如:逗号分隔标记

scanner.useDelimiter(",");

注意:设置分隔符会影响Scanner识别标记的方式。

3、读取标记:一旦Scanner对象被创建并配置了分隔符,你就可以使用next()nextInt()nextDouble()等方法来读取下一个标记了这些方法会返回输入流中下一个与指定类型匹配的标记。例如:

String token = scanner.next(); // 读取下一个标记作为字符串  
int number = scanner.nextInt(); // 读取下一个标记并尝试将其解析为整数

4、检查是否有下一个标记:在读取标记之前,建议使用hasNext()hasNextLine()方法先检查输入流中是否还有下一个标记或行。这些方法会返回一个布尔值,指示是否还有更多的输入可供读取。例如: 

if (scanner.hasNext()) {  String token = scanner.next();  // 处理标记  
}

5、关闭Scanner对象:完成输入操作后,应该关闭Scanner对象以释放资源。可以通过调用close()方法来实现:(虽然大部分时间没关闭也不会像数据库那样报错)。

scanner.close();


http://www.mrgr.cn/news/64740.html

相关文章:

  • 学习笔记:微服务技术栈(一)服务治理框架SpringCloud
  • 数据挖掘(八)
  • 性能测试 —— MySQL性能测试方案设计!
  • Kafka 消息丢失如何处理?
  • MATLAB绘制水蒸气温度和压力曲线(IAPWS-IF97公式)
  • 勒索软件通过易受攻击的 Cyber​​Panel 实例攻击网络托管服务器
  • Netty 组件介绍 - ChannelFuture
  • ASRPRO 记事本2
  • SICTF Round #4|MISC
  • YOLOv6-4.0部分代码阅读笔记-figure_iou.py
  • diss git使用
  • 德州仪器股票分析:增长已经放缓的德州仪器,该买入还是卖出?
  • SpringBoot自动装配流程
  • 存储和读写方案
  • 讲讲RabbitMQ 性能优化
  • 清华双臂机器人扩散大模型RDT:先预训练后微调,支持语言、图像、动作多种输入
  • 动态规划-两个数组的dp问题——1143.最长公共子序列
  • Java 中的 堆栈(Stack)
  • 海滨学院班级记忆档案:设计与技术实现
  • 单例模式四种写法
  • C#/.NET/.NET Core学习路线集合,学习不迷路!
  • 使用贪心策略求解糖果罐调整次数
  • Foods
  • 三层交换实现不同VLAN之间设备的互通
  • js中多let与var
  • 【016C】基于51单片机电子秤(LCD1602显示)