工作当中对数据集合进行操作最多的使用的就是Java8 的stream流,方便,代码干净,看着舒服,代码也很优雅。我们都知道stream流的流式操作最终生成的都是新的集合,那么工作中使用的时候对stream流新生成的集合里面的数据是否也为新的数据呢,还是说是原有集合里面的数据呢?
一、首先对stream流 生成新的集合验证
代码
@Test
public void test36(){
List<Integer> numList = Arrays.asList(1,2,3,4,5,6);
List<Integer> collect = numList.stream().filter(i -> i > 3).collect(Collectors.toList());
System.out.println("原numList = " + numList);
System.out.println("新collect = " + collect);
collect.add(8);
System.out.println("新collect = " + collect);
System.out.println("原numList = " + numList);
}
运行结果
结论
从运行结果我们可以出来,通过流处理收集起来的集合确实为新生成的集合,无论是对收集的集合进行新增还是修改对原集合都是没有发生改变的,这就证明了Java8 stream流 生成的是新的集合。那么如果假如集合里面是对象呢,如果对新收集的集合进行对象值的修改原集合会发生变化吗?
二、stream流生成的新集合,修改新集合里面对象值原集合的值是否会发生变化?
代码
@Test
public void test35(){
// 原集合
List<Map<String,Object>> innerList_1 = new ArrayList<>();
Map<String,Object> innerMap_1 = new HashMap<>();
innerMap_1.put("name", "wxf1");
innerMap_1.put("age", "17");
Map<String,Object> innerMap_2 = new HashMap<>();
innerMap_2.put("name", "wxf2");
innerMap_2.put("age", "18");
innerList_1.add(innerMap_1);
innerList_1.add(innerMap_2);
System.out.println("原innerList_1 = " + innerList_1);
// 收集集合数据
List<Map<String, Object>> collect = innerList_1.stream().map(m -> {
// 将name都改为www
m.put("name", "www");
return m;
}).collect(Collectors.toList());
for (Map<String, Object> map : collect) {
// 通过for循环对收集数据的age字段都修改为20
map.put("age", 20);
}
// 追加新map到收集的数据中 验证对原有集合不会发生影响
Map<String,Object> innerMap_3 = new HashMap<>();
innerMap_3.put("name", "zjl");
innerMap_3.put("age", "18");
collect.add(innerMap_3);
System.out.println("原innerList_1 = " + innerList_1);
System.out.println("collect = " + collect);
}
运行结果
我们可以看出对收集的新集合修改集合里面对象的值,原数组的值也发生了改变!!!
那是为什么呢?
代码
@Test
public void test35(){
// 原集合
List<Map<String,Object>> innerList_1 = new ArrayList<>();
Map<String,Object> innerMap_1 = new HashMap<>();
innerMap_1.put("name", "wxf1");
innerMap_1.put("age", "17");
Map<String,Object> innerMap_2 = new HashMap<>();
innerMap_2.put("name", "wxf2");
innerMap_2.put("age", "18");
innerList_1.add(innerMap_1);
innerList_1.add(innerMap_2);
System.out.println("原innerList_1 = " + innerList_1);
// 收集集合数据
List<Map<String, Object>> collect = innerList_1.stream().map(m -> {
// 验证是否使用的是同一地址值 如果进入判断 == 判断的则是对象的地址值是否想等
if (innerMap_1 == m) {
System.out.println("innerMap_1 == m");
}
if (innerMap_2 == m) {
System.out.println("innerMap_2 == m");
}
return m;
}).collect(Collectors.toList());
for (Map<String, Object> map : collect) {
// 通过for循环对收集数据的age字段都修改为20
map.put("age", 20);
}
// 追加新map到收集的数据中 验证对原有集合不会发生影响
Map<String,Object> innerMap_3 = new HashMap<>();
innerMap_3.put("name", "zjl");
innerMap_3.put("age", "18");
collect.add(innerMap_3);
System.out.println("原innerList_1 = " + innerList_1);
System.out.println("collect = " + collect);
}
运行结果
结论
由上面验证我们可以得出一个结论,就是我们在使用stream流的时候,生成的集合的的确确就是新集合,无论你对收集的集合进行新增对象还是删除对象对原有集合都没有影响到,但是如果你对收集起来的集合里面的对象进行修改值,那么原集合中的对象的值也会发生变化,因为从代码验证我们可以发现收集的集合里面的对象和原集合中的对象引用的地址值是一模一样的,所以当我们改变收集起来的集合对象里面的值,原集合里面的对象里面的值页一样会进行修改。这有点类似于浅拷贝,而不像深拷贝一样会生成一个新的地址,复制其所有属性值。