应使用ArrayList而非数组,因其自动扩容、类型安全;需重写equals/hashCode、避免遍历时直接remove、预估容量初始化、谨慎选用TreeSet排序、推荐JSON序列化并处理兼容性。
ArrayList 而不是数组存联系人数组长度固定,增删联系人时得手动复制、扩容,容易出错;ArrayList 自动处理这些,且支持泛型约束类型安全。别写 Object[] 或 Contact[] —— 后者删一个元素就得自己移动后续所有引用,ArrayList.remove(int) 已经帮你做了。
注意点:
ArrayList 查找慢(O(n)),如果频繁按姓名查,后面得补 HashMap 索引ArrayList 时直接调用 remove(),会抛 ConcurrentModificationException;改用 Iterator.remove() 或倒序 for 循环new ArrayList() 就完事——预估联系人上限(比如 200),写成 new ArrayList(200),避免多次扩容拷贝Contact 类必须重写 equals() 和 hashCode()
否则用 list.contains(new Contact("张三")) 永远返回 false,因为默认比较的是内存地址。只要 name 和 phone 相同就认为是同一人,就得按这两个字段生成哈希码。
示例关键片段:
public class Contact {
private String name;
private String phone;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Contact contact = (Contact) o;
return Objects.equals(name, contact.name) &&
Objects.equals(phone, contact.phone);
}
@Override
public int hashCode() {
return Objects.hash(name, phone);
}
}
别漏掉 Objects 工具类——它自动处理 null 安全,比手写 name != null ? name.hashCode() : 0 更可靠。
TreeSet 实现自动排序通讯录如果希望每次添加
后联系人按姓名拼音或字母序排列,不用每次 Collections.sort(),直接用 TreeSet,但前提是 Contact 实现 Comparable 接口。
常见陷阱:
name 字段比较——万一重名呢?得加 phone 作为第二排序条件,否则 TreeSet 会把两个同名不同号的人当成重复项丢掉compareTo() 里调用 String.toUpperCase() 做忽略大小写比较——中文拼音排序会乱,改用 Collator.getInstance(Locale.CHINA)
TreeSet 不允许 null 元素,插入前务必检查 contact != null
Serializable 不是唯一选择用 ObjectOutputStream 写 ArrayList 是最直白的方式,但二进制格式不跨 Java 版本、不可读、难调试。实际开发中更推荐 JSON:
Gson 或 Jackson 库,一行就能序列化:gson.toJson(contacts, new TypeToken>(){}.getType())
Serializable,记得给 Contact 加 private static final long serialVersionUID = 1L;,否则类结构稍变(比如加个字段)反序列化就失败文件路径别硬编码 "contacts.dat",用 System.getProperty("user.home") + "/contacts.json" 更稳妥。
真正麻烦的不是存取逻辑,而是字段变更后的兼容性——比如某天加了 email 字段,旧 JSON 文件没这字段,Gson 默认会设为 null,但你的业务代码得能容忍这个 null。