You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java如何实现按空格触发的控制台逐词读取?

在Java中实现逐词读取控制台输入(按空格触发)

当然可以实现!你遇到的Scanner局限很正常——它依赖输入缓冲区的换行来触发读取动作,所以必须等用户按下回车才会返回结果。要实现按下空格就立即读取此前输入的单词,我们需要直接操作底层的标准输入流,逐字符处理输入内容,自己控制单词的提交时机。

结合你提到的多线程项目背景(一个线程读输入、一个线程显示单词计数),下面是具体的实现方案:

核心思路

  • 用System.in.read()逐字符读取控制台输入,绕过Scanner的缓冲区限制
  • 维护一个临时字符串,动态拼接用户输入的字符,直到遇到空格(或回车)
  • 遇到分隔符时,将临时字符串作为单词存入线程安全的集合(因为多线程共享数据必须保证线程安全)
  • 显示线程定期读取集合内容,输出单词及其计数

完整代码示例

1. 输入读取线程(负责捕获空格触发的单词)

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

public class InputReaderThread extends Thread {
    private final ConcurrentHashMap<String, Integer> wordCounts;

    // 传入共享的线程安全计数集合
    public InputReaderThread(ConcurrentHashMap<String, Integer> wordCounts) {
        this.wordCounts = wordCounts;
    }

    @Override
    public void run() {
        StringBuilder currentWord = new StringBuilder();
        try {
            int charCode;
            // 循环读取每个字符,直到输入结束(Ctrl+C)
            while ((charCode = System.in.read()) != -1) {
                char inputChar = (char) charCode;
                
                // 遇到空格或回车时,提交当前单词
                if (inputChar == ' ' || inputChar == '\n') {
                    if (currentWord.length() > 0) {
                        String word = currentWord.toString().trim();
                        // 线程安全地更新单词计数:不存在则设为1,存在则加1
                        wordCounts.put(word, wordCounts.getOrDefault(word, 0) + 1);
                        currentWord.setLength(0); // 重置临时字符串,准备下一个单词
                    }
                    // 按下回车时结束输入(可根据需求调整退出逻辑)
                    if (inputChar == '\n') {
                        System.out.println("\n输入已结束,程序将在3秒后退出...");
                        Thread.sleep(3000);
                        break;
                    }
                } else {
                    // 非分隔符字符,拼接进当前单词
                    currentWord.append(inputChar);
                }
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

2. 计数显示线程(负责实时展示单词统计)

import java.util.concurrent.ConcurrentHashMap;

public class WordCountDisplayThread extends Thread {
    private final ConcurrentHashMap<String, Integer> wordCounts;
    private volatile boolean isRunning = true; // 线程终止标记

    public WordCountDisplayThread(ConcurrentHashMap<String, Integer> wordCounts) {
        this.wordCounts = wordCounts;
    }

    @Override
    public void run() {
        while (isRunning) {
            try {
                // 每秒刷新一次显示内容
                Thread.sleep(1000);
                System.out.print("\r当前单词统计:"); // 用\r覆盖上一行输出,避免刷屏
                wordCounts.forEach((word, count) -> System.out.printf("%s:%d ", word, count));
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                isRunning = false;
            }
        }
    }

    // 提供外部终止线程的方法
    public void stopDisplay() {
        isRunning = false;
    }
}

3. 主程序(启动两个线程)

import java.util.concurrent.ConcurrentHashMap;

public class WordCounterApp {
    public static void main(String[] args) {
        // 用ConcurrentHashMap保证多线程下的读写安全
        ConcurrentHashMap<String, Integer> wordCounts = new ConcurrentHashMap<>();

        InputReaderThread readerThread = new InputReaderThread(wordCounts);
        WordCountDisplayThread displayThread = new WordCountDisplayThread(wordCounts);

        // 启动线程
        readerThread.start();
        displayThread.start();

        try {
            // 等待输入线程结束,再终止显示线程
            readerThread.join();
            displayThread.stopDisplay();
            displayThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

关键注意事项

  • 线程安全:必须使用ConcurrentHashMap这类线程安全的容器,避免多线程读写时出现数据混乱
  • 输入扩展:如果需要支持制表符、换行符等其他分隔符,可以把判断条件改成Character.isWhitespace(inputChar)
  • 大小写处理:如果需要忽略大小写统计(比如Hello和hello算同一个单词),可以在提交时转成小写:word.toLowerCase()
  • 退出逻辑:示例中用回车结束输入,你也可以改成按特定字符(比如q)触发退出

内容的提问来源于stack exchange,提问作者user3578760

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:02:20