在 java 中,数组的复制涉及深浅拷贝问题。以下是几种常用的方法:
1.浅拷贝(shallow copy)
只复制数组的引用,不复制数组元素本身。
方法一:使用=赋值(只是引用复制)
int[] original = {1, 2, 3, 4, 5};
int[] shallowcopy = original; // 只是引用复制
original[0] = 100;
system.out.println(shallowcopy[0]); // 输出 100,两个数组指向同一对象
方法二:clone()方法(数组浅拷贝)
// 对于基本类型数组,clone() 是深拷贝
int[] original = {1, 2, 3, 4, 5};
int[] copy = original.clone();
original[0] = 100;
system.out.println(copy[0]); // 输出 1,因为是基本类型数组
// 对于对象数组,clone() 是浅拷贝
person[] persons = {new person("alice"), new person("bob")};
person[] shallowcopy = persons.clone();
persons[0].setname("charlie");
system.out.println(shallowcopy[0].getname()); // 输出 "charlie"
方法三:arrays.copyof()
int[] original = {1, 2, 3, 4, 5};
int[] copy = arrays.copyof(original, original.length);
// 对于对象数组
person[] persons = {new person("alice"), new person("bob")};
person[] shallowcopy = arrays.copyof(persons, persons.length);
方法四:system.arraycopy()
int[] original = {1, 2, 3, 4, 5};
int[] copy = new int[original.length];
system.arraycopy(original, 0, copy, 0, original.length);
2.深拷贝(deep copy)
复制数组及其所有元素(包括嵌套对象)。
方法一:手动复制(推荐)
// 对于对象数组
class person implements cloneable {
private string name;
public person(string name) { this.name = name; }
@override
protected object clone() throws clonenotsupportedexception {
return super.clone(); // 假设 person 是浅拷贝可接受的
// 或者返回 new person(this.name); // 深拷贝
}
}
// 深拷贝实现
person[] original = {new person("alice"), new person("bob")};
person[] deepcopy = new person[original.length];
for (int i = 0; i < original.length; i++) {
// 假设 person 类有合适的拷贝构造方法
deepcopy[i] = new person(original[i].getname());
// 或者使用 clone()
// deepcopy[i] = (person) original[i].clone();
}
方法二:使用序列化(完全深拷贝)
import java.io.*;
public class deepcopyutil {
@suppresswarnings("unchecked")
public static <t extends serializable> t deepcopy(t obj) {
try {
bytearrayoutputstream bos = new bytearrayoutputstream();
objectoutputstream oos = new objectoutputstream(bos);
oos.writeobject(obj);
oos.flush();
bytearrayinputstream bis = new bytearrayinputstream(bos.tobytearray());
objectinputstream ois = new objectinputstream(bis);
return (t) ois.readobject();
} catch (exception e) {
throw new runtimeexception(e);
}
}
}
// 使用
person[] persons = {new person("alice"), new person("bob")};
person[] deepcopy = deepcopy(persons);
方法三:使用库工具(如 apache commons lang)
// 添加依赖:org.apache.commons:commons-lang3
import org.apache.commons.lang3.serializationutils;
// 对象必须实现 serializable
person[] persons = {new person("alice"), new person("bob")};
person[] deepcopy = serializationutils.clone(persons);
3.多维数组的深拷贝
// 二维数组深拷贝
int[][] original = {{1, 2}, {3, 4}};
int[][] deepcopy = new int[original.length][];
for (int i = 0; i < original.length; i++) {
deepcopy[i] = original[i].clone(); // 对于基本类型数组有效
}
// 对象二维数组
person[][] persons = {{new person("alice")}, {new person("bob")}};
person[][] deepcopy = new person[persons.length][];
for (int i = 0; i < persons.length; i++) {
deepcopy[i] = new person[persons[i].length];
for (int j = 0; j < persons[i].length; j++) {
deepcopy[i][j] = new person(persons[i][j].getname());
}
}
4.java 8+ 的流式操作
import java.util.arrays;
// 对象数组深拷贝(需要合适的构造方法)
person[] original = {new person("alice"), new person("bob")};
person[] deepcopy = arrays.stream(original)
.map(p -> new person(p.getname()))
.toarray(person[]::new);
总结
| 方法 | 类型 | 特点 | 适用场景 |
|---|---|---|---|
| = 赋值 | 引用复制 | 最快,但共享同一对象 | 不需要独立副本时 |
| clone() | 浅拷贝/深拷贝 | 基本类型数组是深拷贝 | 基本类型数组复制 |
| arrays.copyof() | 浅拷贝 | 简洁易用 | 对象数组浅拷贝 |
| system.arraycopy() | 浅拷贝 | 高效,底层实现 | 性能要求高的场景 |
| 手动循环 | 可深可浅 | 最灵活 | 需要完全控制拷贝过程 |
| 序列化 | 深拷贝 | 完全独立,但性能差 | 需要完全深拷贝,对象图复杂 |
| java 8 stream | 可深可浅 | 函数式风格 | 现代 java 代码 |
选择建议:
- 基本类型数组:使用
clone()、arrays.copyof()或system.arraycopy() - 对象数组浅拷贝:使用
arrays.copyof()或system.arraycopy() - 对象数组深拷贝:手动实现或使用序列化
- 复杂对象图:考虑使用序列化或第三方库(如 apache commons lang)
到此这篇关于java实现数组的复制及深浅拷贝的常见方法总结的文章就介绍到这了,更多相关java数组复制与拷贝内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论