如何使用Java开发记账本小程序_Java条件判断与集合应用说明

Java记账本中用if判断收支类型更灵活,适合范围判断;switch在Java 14+支持字符串和yield,语法更简洁,但需注意null安全及版本兼容性。

Java记账本里怎么用 ifswitch 判断收支类型

记账本最基础的逻辑就是区分“收入”和“支出”,不能靠人工肉眼识别,得让程序自动判断。常见做法是给每条记录加一个 type 字段(比如 "INCOME""EXPENSE"),再用条件语句分流处理。

if 更灵活,适合带范围判断的场景(比如金额大于1000算“大额支出”);switch 在 Java 14+ 支持字符串和 yield,写起来更干净,但注意旧版本只支持 String、枚举和基本类型。

  • 别直接比较字符串用 ==,必须用 "INCOME".equals(record.getType())
  • 如果 type 字段可能为 null,先判空再 equals,否则抛 NullPointerException
  • 多个并列类型(如 "SALARY""BONUS""TRANSFER")都算收入,switchcase 可以合并写:
    case "SALARY", "BONUS", "TRANSFER" -> totalIncome += record.getAmount();

ArrayList 还是 LinkedHashMap 存账单数据

初学者常默认用 ArrayList,确实简单,增删查都快,但记账本有两类高频操作:按日期排序展示、按月份统计总额——这时候 ArrayList 就得反复 sort() 或遍历过滤,效率低还容易漏逻辑。

LinkedHashMap

身不解决排序问题,但它能配合 TreeMap 按时间建索引,或者你用 LocalDate 作 key,把当天所有账单塞进 ArrayList 值里:

Map> dailyRecords = new TreeMap<>(Collections.reverseOrder());

这样查某天账单是 O(1),按月汇总只要遍历 keySet 并过滤 getYear()getMonth() 即可。代价是内存稍高,但对几百条账单完全无感。

  • 别用 HashMap 存日期 key——它不保证顺序,遍历时日期乱序,UI 上看着就懵
  • 如果要做“最近7天”查询,用 TreeMap.subMap(from, to) 比循环判断快得多
  • 删除某条记录时,记得同步从对应日期的 Listremove(),否则数据不一致

Java 8 Stream 处理账单集合时的三个坑

records.stream().filter(...).map(...).collect(...) 写统计逻辑很简洁,但实际跑起来可能出错或变慢。

  • filter 里别调用可能抛异常的方法(比如解析字符串日期),要包 try-catch 或提前校验,否则整个流中断
  • 避免在 map 里做 IO 操作(如读配置文件、查数据库),Stream 默认是单线程,阻塞会拖慢全部流程
  • 统计月支出总额时,别写 records.stream().filter(r -> r.getType().equals("EXPENSE")).mapToDouble(Record::getAmount).sum() —— 这样每次都要全量扫描;应该先按 type 分组缓存:
    Map summary = records.stream()
        .collect(Collectors.groupingBy(Record::getType, Collectors.summingDouble(Record::getAmount)));

为什么不用 VectorStack 存账单

有些老教程推荐用 Vector,说“线程安全”,但记账本小程序基本是单用户本地运行,根本不需要同步开销;Vector 每个方法都加 synchronized,性能比 ArrayList 低 20%~30%。

Stack 更不合适——它是后进先出结构,而账单天然按时间先后排列,用 push/pop 反而得倒着插、倒着取,逻辑绕且易错。

  • 真需要线程安全集合,用 Collections.synchronizedList(new ArrayList())CopyOnWriteArrayList(仅适用于读多写少)
  • 如果未来要加“撤销上一笔”功能,别用 Stack,改用 Deque(比如 ArrayDeque),addLast()removeLast() 语义更清晰
  • 所有集合变量声明用接口类型:List records,而不是 ArrayList,方便以后换实现
实际开发中,最常被忽略的是日期字段的不可变性——LocalDate 没问题,但若用了 Date 或自己写的可变 MyDate 类,被误修改会导致统计结果错乱,且极难排查。