Java Stream toArray 对象深拷贝
在Java中,Stream API是一个非常强大和灵活的工具,用于对集合数据进行处理和操作。使用Stream API,我们可以将集合数据进行过滤、映射、排序等操作,使代码更加简洁和可读。在Stream API中,toArray()是一个常用的终端操作,用于将数据流转换为数组。但是,对于包含对象的数据流,需要注意默认情况下toArray()方法返回的是浅拷贝,即数组中的元素和原始数据流中的元素引用的是同一个对象。如果我们希望进行对象的深拷贝,就需要特殊处理。
本文将介绍如何使用Java的Stream API中的toArray()方法进行对象的深拷贝,并通过代码示例进行说明。
浅拷贝和深拷贝
在开始之前,我们先来了解一下浅拷贝和深拷贝的概念。
-
浅拷贝:将一个对象的引用复制给另一个对象,复制后的对象与原始对象引用的是同一个对象。如果修改复制后的对象,原始对象也会受到影响。
-
深拷贝:将一个对象复制给另一个对象,复制后的对象与原始对象没有任何关联。修改复制后的对象不会影响原始对象。
在Java中,对于基本类型(如int、float等)的数组,使用Arrays.copyOf()方法可以实现深拷贝。但是对于包含对象的数组,Arrays.copyOf()只能实现浅拷贝。而Stream API中的toArray()方法默认也只能实现浅拷贝,需要我们自己进行处理,才能实现对象的深拷贝。
使用Stream.toArray()实现对象深拷贝
在Java 8中,Stream API引入了toArray()方法,用于将数据流转换为数组。默认情况下,toArray()方法返回的是一个Object数组,其元素与原始数据流中的元素是浅拷贝的关系。为了实现对象的深拷贝,我们可以通过自定义Collector的方式来实现。
下面是一个自定义Collector的示例代码:
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
class DeepCloneCollector<T> implements Collector<T, List<T>, List<T>> {
@Override
public Supplier<List<T>> supplier() {
return ArrayList::new;
}
@Override
public BiConsumer<List<T>, T> accumulator() {
return List::add;
}
@Override
public BinaryOperator<List<T>> combiner() {
return (list1, list2) -> {
list1.addAll(list2);
return list1;
};
}
@Override
public Function<List<T>, List<T>> finisher() {
return Function.identity();
}
@Override
public Set<Characteristics> characteristics() {
return Collections.emptySet();
}
}
在上面的代码中,我们定义了一个DeepCloneCollector类,实现了Collector接口的几个方法。这里我们使用ArrayList作为容器,通过add方法将元素添加到容器中。在combiner方法中,我们将两个容器合并成一个。
通过使用自定义Collector,我们可以将Stream流转换为一个深拷贝的List对象。下面是一个示例代码:
import java.util.*;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Main {
public static void main(String[] args) {
List<Person> persons = Arrays.asList(
new Person("Alice", 20),
new Person("Bob", 25),
new Person("Charlie", 30)
);
List<Person> deepCopy = persons.stream().collect(new DeepCloneCollector<>());
System.out.println(deepCopy);
// Output: [Person{name='Alice', age=20}, Person{name='Bob', age=25