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

用 ArrayList 存员工对象而不是 String 或 int
很多人一开始想“存名字用 ArrayList,存工号用 ArrayList”,结果很快发现:增删查改时根本没法关联——改了名字找不到对应工号。必须封装成一个实体类,再用 ArrayList 统一管理。
实操建议:
-
Employee类至少包含id(int或String)、name、department、salary字段,并补全构造方法和toString() - 避免用
ArrayList模拟对象——类型不安全,编译期无法检查字段名拼写错误 - 如果后续要按 ID 快速查找,别硬写遍历循环,先记着:
HashMap才是更合适的结构(但集合练习阶段仍建议从ArrayList开始)
增删改查时别直接操作原始 list 引用
比如写了个方法 public void deleteById(ArrayList,然后在方法里执行 list.remove(i) —— 表面看没问题,但调用方传入的 list 被直接修改,容易引发并发修改或意外状态丢失。
常见错误现象:
立即学习“Java免费学习笔记(深入)”;
- 删除后再次查询,发现数据还在(其实是没删对索引,或用了
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——这些不会导致程序崩溃,却会让使用者反复怀疑“是不是我输错了”。










