hashmap深克隆需确保值对象深度复制,推荐手动遍历+构造函数(可控高效)或序列化(通用但性能低),禁用继承重写clone()。

Java 中 HashMap 本身不支持真正的深度克隆,它的 clone() 和构造函数(如 new HashMap(original))都只做浅拷贝——键和值对象的引用被复制,但值对象内部状态仍共享。要实现“深度克隆”,关键不是改造 HashMap,而是确保它所存储的**值对象本身可深度复制**,并选用合适的方式组合完成整张映射的深拷贝。
明确深克隆的边界:值对象决定深度
HashMap 的深克隆 = 对每个 key 和 value 都执行深拷贝。但 key 通常用不可变类型(如 String、Integer),无需额外处理;真正需要关注的是 value——尤其是自定义对象、List、Map、StringBuilder 等可变引用类型。
例如:Map<string person></string> 要深克隆,必须保证每个 Person 实例也被深拷贝,否则修改副本中的 person.name 仍会影响原 map 里的 person。
推荐方案:构造函数 + 值对象手动深拷贝(最可控)
适用于 value 类型明确、数量可控的场景。不依赖反射或序列化,性能好、逻辑清晰、易于调试。
- 遍历原 map,对每个 entry 创建新 key(若 key 可变则也要 clone)和深拷贝后的 value
- value 深拷贝方式取决于其类型:
- 自定义类:提供
clone()方法或拷贝构造函数,并递归处理其字段 -
List/Set:用new ArrayList(originalList)(仅当元素不可变或已深拷贝) -
Map:同理,用new HashMap(originalSubMap)并确保子 map 的 value 也深拷贝 -
StringBuilder:用new StringBuilder(originalSB)
- 自定义类:提供
示例:
Map<string person> deepClone(Map<string person> original) {<br> Map<string person> clone = new HashMap();<br> for (Map.Entry<string person> e : original.entrySet()) {<br> clone.put(e.getKey(), e.getValue().clone()); // Person 已实现深 clone<br> }<br> return clone;<br>}</string></string></string></string>
通用兜底方案:序列化反序列化(适合复杂嵌套)
当 value 类型多变、嵌套深、且所有相关类都可序列化时,这是最省力的通用解法。本质是把对象图转成字节流再重建,天然保证深度隔离。
- 要求所有 value(及它们的字段)实现
Serializable - 注意 transient 字段不会被复制,静态字段不参与序列化
- 性能略低(涉及 IO 和反射),但语义最严谨
可用工具类封装(如 Apache Commons Lang 的 SerializationUtils.clone()),或手写:
public static <k extends serializable> Map<k> deepCloneBySer(Map<k> original) throws IOException, ClassNotFoundException {<br> ByteArrayOutputStream bos = new ByteArrayOutputStream();<br> ObjectOutputStream oos = new ObjectOutputStream(bos);<br> oos.writeObject(original);<br> oos.close();<br> ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());<br> ObjectInputStream ois = new ObjectInputStream(bis);<br> @SuppressWarnings("unchecked")<br> Map<k> clone = (Map<k>) ois.readObject();<br> ois.close();<br> return clone;<br>}</k></k></k></k></k>
不推荐的做法:直接重写 HashMap.clone()
像早期资料中那样继承 HashMap 并在 clone() 里遍历 put,看似“深”,实则仍是浅拷贝——它只新建了 HashMap 容器,里面的 value 引用并未复制。除非你在循环中显式调用每个 value 的深拷贝方法,否则毫无意义。
更严重的是:HashMap 不是为继承设计的(缺乏 protected 方法、文档未承诺子类兼容性),强行继承易出问题,违背封装原则。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











