用scanner读输入、arraylist存留言实现增删查:新增校验空内容,删除时序号减1转换,遍历用增强for;退出前用utf-8编码文件保存,scanner需全局共享避免重复创建。

如何用 Scanner + ArrayList 实现留言增删查
控制台留言板本质是内存中的数据管理,不需要数据库。核心就是用 ArrayList<string></string> 存留言,配合 Scanner 读用户输入。别一上来就搞文件持久化或 Swing 界面,先跑通基本流程。
常见错误:直接用 System.in.read() 读字符串,结果只拿到第一个字符;或者用 next() 而不是 nextLine(),导致换行符残留、后续输入跳过。
- 始终用
scanner.nextLine()读整行输入(包括空格和中文) - 新增留言时,建议对内容做基础校验:
if (content.trim().isEmpty())跳过空提交 - 删除按序号操作时,注意
list.remove(index)的索引从 0 开始,但显示给用户时通常从 1 开始,记得减 1 - 遍历输出用增强 for 循环即可,不需要手写
for (int i = 0; i —— 容易越界
为什么不能用 String[] 而必须用 ArrayList
留言数量不确定,String[] 初始化后长度固定。每次新增都要新建数组、复制元素,效率低且代码臃肿。而 ArrayList 内部自动扩容,接口简洁。
典型翻车场景:声明 String[] messages = new String[5];,填满后用户再发第 6 条,程序直接抛 ArrayIndexOutOfBoundsException,而不是友好提示“已满”。
立即学习“Java免费学习笔记(深入)”;
-
ArrayList的add()和remove()时间复杂度平均 O(1),足够应付百条以内留言 - 如果真要限制最大条数,用
if (list.size() >= MAX_SIZE)判断,比手动管理数组下标清晰得多 - 别为了“省事”用静态数组 + 全局计数器变量,容易在多处修改时不同步
如何让退出前自动保存到本地文件
纯控制台程序关闭即丢数据,用户会抱怨“刚写的留言没了”。用 FileWriter + BufferedWriter 在退出前 dump 到 messages.txt 即可,不用上 ObjectOutputStream 序列化。
关键陷阱:路径没写对、没关流、中文乱码。Windows 默认编码是 GBK,但 IDE(如 IntelliJ)常设 UTF-8,不指定编码会写成乱码。
- 保存时强制指定编码:
new OutputStreamWriter(new FileOutputStream("messages.txt"), "UTF-8") - 务必在
finally块或 try-with-resources 中关闭BufferedWriter,否则可能内容没真正写入磁盘 - 启动时若文件存在,用
Files.readAllLines(Paths.get("messages.txt"), StandardCharsets.UTF_8)加载,比手动逐行读更安全 - 不要在每次增删都实时写文件——IO 操作慢,且频繁写可能被杀毒软件拦截
怎样避免 main 方法里堆满 if-else 分支逻辑
把菜单选择、功能执行拆成独立方法,比如 showMenu()、handleAdd()、handleList()。main 只负责循环调用和分发,否则 200 行全挤在一块,改个提示语都怕牵出 bug。
另一个常见混乱点:把 Scanner 创建放在方法内部,导致多次 new Scanner(System.in) —— 第二次调用会报 IllegalStateException: Scanner closed。
-
Scanner必须作为类成员变量或传参共享,不能每个方法都 new 一个 - 菜单循环用
while (true)+break最直白,别硬套 do-while 或状态机 - 输入非数字时,
scanner.hasNextInt()要配合scanner.next()清掉非法 token,否则会无限卡在同一次输入
最易忽略的是输入缓冲区残留:比如用户输完“3”想删除,回车后 nextLine() 立刻返回空字符串。这不是 bug,是 nextInt() 不吃换行符的正常行为。要么统一用 nextLine() 后 parse,要么每次 nextInt() 后跟一句 scanner.nextLine() 吸掉回车。










