在Java中如何开发简易员工管理系统_Java集合应用实践解析

应使用ArrayList统一管理员工对象,而非分开存储字段;Employee类需封装id、name等字段并实现构造方法和toString();避免用Map模拟对象或直接操作原始list引用,删除时用索引而非对象值,查询频繁时考虑HashMap索引,序列化需显式声明serialVersionUID。

用 ArrayList 存员工对象而不是 String 或 int

很多人一开始想“存名字用 ArrayList,存工号用 ArrayList”,结果很快发现:增删查改时根本没法关联——改了名字找不到对应工号。必须封装成一个实体类,再用 ArrayList 统一管理。

实操建议:

  • Employee 类至少包含 idintString)、namedepartmentsalary 字段,并补全构造方法和 toString()
  • 避免用 ArrayList> 模拟对象——类型不安全,编译期无法检查字段名拼写错误
  • 如果后续要按 ID 快速查找,别硬写遍历循环,先记着:HashMap 才是更合适的结构(但集合练习阶段仍建议从 ArrayList 开始)

增删改查时别直接操作原始 list 引用

比如写了个方法 public void deleteById(ArrayList list, int id),然后在方法里执行 list.remove(i) —— 表面看没问题,但调用方传入的 list 被直接修改,容易引发并发修改或意外状态丢失。

常见错误现象:

  • 删除后再次查询,发现数据还在(其实是没删对索引,或用了 remove(Object) 误删第一个匹配元素)
  • 添加员工后,其他地方遍历 list 出现 ConcurrentModificationException(尤其在 for-each 循环中边遍历边 remove)
  • 传入的 list 是某个静态变量或共享缓存,被无意污染

实操建议:

  • 删除务必用索引方式:
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i).getId() == id) {
            list.remove(i);
            break;
        }
    }
  • 或者用迭代器安全删除:
    Iterator it = list.iterator();
    while (it.hasNext()) {
        if (it.next().getId() == id) {
            it.remove();
            break;
        }
    }
  • 增/改操作无需额外防护,但建议所有业务方法都以 void 返回,不返回 list 引用,避免链式调用误导

按条件查询别写三重嵌套 if + for

比如“查工资大于 8000 且部门为技术部的员工”,有人会这样写:

for (Employee e : list) {
    if (e.getSalary() > 8000) {
        if ("技术部".equals(e.getDepartment())) {
            result.add(e);
        }
    }
}
逻辑没错,但可读性差、难扩展,而且一旦加个“姓名含‘张’”的条件,立刻变四层。

实操建议:

  • 把筛选逻辑抽成独立方法:boolean matches(Employee e, double minSalary, String dept),主流程只剩一层 for
  • Java 8+ 推荐用 Stream(但注意:练习集合基础时不建议跳过传统写法):
    list.stream()
        .filter(e -> e.getSalary() > 8000)
        .filter(e -> "技术部".equals(e.getDepartment()))
        .collect(Collectors.toList());
  • 如果查询频繁且数据量超 500 条,ArrayList 的 O(n) 查找会明显卡顿——这时就得考虑是否该换 HashMap 做索引,或引入简易内存数据库如 H2

序列化保存到文件时避开 serialVersionUID 报错

ObjectOutputStream 写员工列表到 employees.dat,第一次能读,第二次运行就抛 InvalidClassException,提示 Employee; local class incompatible: stream classdesc serialVersionUID

这是因为 JVM 自动计算的 serialVersionUID 会随字段增减/类型变更而变化,导致反序列化失败。

实操建议:

  • Employee 类里显式声明:
    private static final long serialVersionUID = 1L;
    (初学者用 1L 即可,上线项目才需按规范生成)
  • 不要用 ArrayList 直接序列化——它内部有 transient 字段,反序列化后可能 size 正确但内容为空;应确保 Employee 本身可序列化且字段非 transient
  • 更轻量的替代方案:用 PrintWriter 写 CSV(id,name,dept

    ,salary
    ),用 Scanner 按行解析——虽然不支持复杂对象嵌套,但调试友好、人眼可读
实际开发中,最常被忽略的是「边界校验」:新增员工时没检查 id 是否重复,删除时传入不存在的 id 不报错也不提示,查不到人就返回空 list——这些不会导致程序崩溃,却会让使用者反复怀疑“是不是我输错了”。