stream api本身不提供深拷贝能力,而是通过map()配合构造函数或序列化实现对象逐个复制,确保集合及内部对象均为新实例,避免状态共享。

用Stream API做对象变量的深拷贝,本质不是Stream本身提供深拷贝能力,而是借助它“遍历+映射”的链式结构,把每个对象逐个复制,再组合成新集合。关键在于:复制动作必须真正创建新实例,不能只是引用传递。
明确深拷贝目标:变量值独立,状态不共享
深拷贝要解决的核心问题是状态污染——比如修改副本中的List元素,原对象不受影响;修改副本中某个嵌套对象的字段,原对象里对应对象也不变。这要求:
- 集合类(如List、Map)需新建容器,并逐项复制其内容
- 集合内的每个元素如果是自定义对象,也必须是新实例(不能直接赋值引用)
- 基本类型和String天然满足深拷贝语义,无需额外处理
推荐做法:用Stream.map()配合构造函数或拷贝逻辑
这是最清晰、可控性最强的方式,适合已知对象结构的场景。以Person类为例:
Person类需支持显式复制逻辑:
class Person {
String name;
List<string> hobbies;
// 原始构造
Person(String name, List<string> hobbies) {
this.name = name;
this.hobbies = new ArrayList(hobbies); // 浅层复制List,但String不可变,安全
}
// 拷贝构造:确保hobbies也是新List,且内部String仍为原值(无需深拷)
Person(Person other) {
this.name = other.name;
this.hobbies = other.hobbies != null
? new ArrayList(other.hobbies)
: null;
}
}</string></string>
使用Stream实现批量深拷贝:
List<person> original = Arrays.asList(
new Person("Alice", Arrays.asList("reading", "hiking")),
new Person("Bob", Arrays.asList("coding"))
);
List<person> copied = original.stream()
.map(Person::new) // 调用拷贝构造函数
.collect(Collectors.toList());</person></person>
此时copied与original完全隔离:改copied.get(0).hobbies.add("swimming"),不影响original。
通用型方案:结合序列化实现任意对象深拷贝
当对象结构复杂、嵌套层级深、或你无法修改类源码时,可利用Java序列化机制 + Stream配合。前提是所有相关类都实现Serializable接口。
封装一个工具方法:
public static <t extends serializable> T serializeCopy(T obj)
throws IOException, ClassNotFoundException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(obj);
try (ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis)) {
return (T) ois.readObject();
}
}
}</t>
在Stream中使用:
List<person> copiedViaSer = original.stream()
.map(p -> {
try {
return serializeCopy(p);
} catch (Exception e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.toList());</person>
注意:static字段、transient字段不会被复制;含非Serializable成员会抛异常;性能低于构造函数方式,慎用于高频调用。
避坑提醒:toArray()和collect()默认都是浅拷贝
以下写法不构成深拷贝:
Person[] copiedArray = original.stream().toArray(Person[]::new); // ❌ 引用未变 List<person> copiedList = original.stream().collect(Collectors.toList()); // ❌ 同一对象引用</person>
它们只新建了容器(数组/List),但容器里的Person对象仍是原引用。若需深拷贝数组,必须先map转换再toArray:
Person[] deepCopiedArray = original.stream()
.map(Person::new) // 每个都走拷贝构造
.toArray(Person[]::new); // ✅
不复杂但容易忽略:Stream只是管道,复制动作得由你明确写出来。选构造函数还是序列化,取决于你对控制力、性能和兼容性的权衡。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











