当前位置: 首页 > 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.lryc.cn/news/477008.html

相关文章:

  • react使用Fullcalendar 实战用法
  • 优秀项目经理必知的10款项目管理软件推荐
  • 植物神经紊乱不用怕,这些维生素来帮你!
  • NRF52832学习笔记(41)——添加串口库libuarte
  • Moore Perf System 1.1版本
  • SpringBoot+Shirp的权限管理
  • OpenCV图像基础
  • 基于MATLAB的图像拼接技术
  • ComfyUI 快速入门(环境搭建)
  • 将HTML项目上传至Gitee仓库(详细教程)
  • 如何应对Oracle SQL语句的数据去重问题,应该考虑哪几个方面?
  • 论负载均衡技术在Web系统中的应用论文
  • NumPy 数据类型
  • JavaScript——(4)
  • 每日一练 | DHCP Relay(DHCP 中继)
  • `psdparse`:解锁Photoshop PSD文件的Python密钥
  • 考研要求掌握的C语言程度(插入排序)
  • mybatis源码解析-sql执行流程
  • Golang | Leetcode Golang题解之第538题把二叉搜索树转换为累加树
  • 【linux】HTTPS 协议原理
  • 安利一款开源企业级的报表系统SpringReport
  • 数据安全-接口数据混合加密笔记
  • JeecgBoot入门
  • 用 Vue.js 打造炫酷的动态数字画廊:展示学生作品的创意之旅
  • 【YOLO学习】YOLOv8改进举例
  • 文心一言 VS 讯飞星火 VS chatgpt (383)-- 算法导论24.5 3题
  • 【AIGC】如何通过ChatGPT轻松制作个性化GPTs应用
  • gulp入门教程2:gulp发展历史
  • 【实验八】前馈神经网络(4)优化问题
  • 【深度学习】论文笔记:空间变换网络(Spatial Transformer Networks)