Java将一个List赋值给另一个List的问题

       最近在写代码的时候发现一个问题:我定义了两个List集合A,B,先对第一个集合A add数据进去,接着直接将A的数据赋值给B,结果后面我将集合A给clear掉,然后使用B集合的数据,结果报了数组越界异常。

最后发现集合B的数据也不存在了。测试代码如下:

List<String> A =new ArrayList<>();
List<String> B =new ArrayList<>();

 A.add("111");
 A.add("222");
 A.add("333");

 B=A;
 System.out.println("A:"+A);
 System.out.println("B:"+B);

 A.clear();
        
 System.out.println("A:"+A);
 System.out.println("B:"+B);

输出结果为:

A:[111, 222, 333]
B:[111, 222, 333]
A:[]
B:[]

 看到这个结果我纳闷了好久,我明明没有将集合B的数据给删掉,只删除了A的数据,为什么B的数据也没了。于是我猜测:

在用B=A 这个方式对集合B进行复制时将集合A对应的地址赋给了集合B,并不是单纯的将集合A的数据赋给集合B。在对A进行clear操作时将A对应的存储空间也就是地址给删除了,那么存储空间里的数据也就随之删除了。而B指向的地址又是A对应的地址,那么B里面的数据也就没有了。

为了印证我的猜测,我查找相关资料后得知:

Java中 "="的作用有两个:

1.赋值

2.指向地址

那么这两个作用具体什么情况下起什么作用呢?答案如下:

当对基本数据类型进行赋值时 "="的作用就是单纯的赋值,例如:int i=1,int j=2;

而当对引用数据类型进行赋值时"="的作用就是将被赋值对象的地址指向赋值对象的地址,例如:

List<String> A =new ArrayList<>();
List<String> B =new ArrayList<>();
A=B;

这里插入讲一下Java堆、栈、常量池的区别:

栈:一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,但对象本身不存放在栈中,而是存放在堆(new出来的对象)或者常量池中(对象可能在常量池里)(字符串常量对象存放在常量池中。)
堆:存放new 出来的对象。
常量池:存放字符串常量和基本类型常量(public static final)。

对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。

注意看上面对栈的描述,当我们定义两个List集合A,B的时候,集合A,B是引用数据类型,那么他们的引用先是在栈内存中分配,而对象本身是在进行new操作的时候存放在堆内存中,由堆进行内存分配。所以我们用B=A这种方式对集合B进行赋值时其实是将A的引用赋值给B,也就是说B指向了A的地址。当对A或是对B进行数据clear,add等操作时相应的B或A中的数据也会发生对应的变化。

最后,如果要将一个List集合赋值给另一个List集合,并且操作其中一个集合不会影响另一个集合时,可以用以下几种方法:

//方法一
ArrayList B = new ArrayList<> (A);

//方法二
B.addAll(A);

//方法三
B = A.clone();

//方法四
for(String s: A)
 B.add(s);

此次出现的问题纠结了我好久,其实也都是很基础的问题,但平时不怎么注意,导致浪费大量时间找寻bug。所以一定要注重基础啊。

特在此记录以下!

 

### 回答1: 在JDK8中,我们可以使用Stream将一个List赋值到另一个List。下面是一个示例代码: List<String> list1 = Arrays.asList("Apple", "Banana", "Orange"); List<String> list2 = list1.stream().collect(Collectors.toList()); 首先,我们有一个包含“Apple”,“Banana”和“Orange”三个元素的List对象list1。 然后,我们使用list1的stream()方法将其转换为一个Stream对象。接着,我们使用Stream的collect()方法,并传入Collectors.toList()作为参数,这将返回一个新的List对象。 最后,我们将新的List对象赋值list2,这样list2中就包含了list1中的所有元素,即“Apple”,“Banana”和“Orange”。 需要注意的是,这种赋值操作实际上是创建了一个新的List对象,并将原始List对象中的元素复制到新的List对象中。这样做是为了避免对原始List对象的修改影响到新的List对象。 希望这个回答对您有帮助! ### 回答2: 在JDK8中,我们可以使用Stream将一个List赋值到另一个List。首先,我们需要创建两个List对象,一个用于存储原始的List数据,另一个用于存储新的List数据。然后,我们可以使用Stream的`forEach`方法遍历原始List,并使用`collect`方法将每个元素收集到新的List中。 以下是使用JDK8 Stream实现将一个List赋值到另一个List的示例代码: ```java import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { // 创建原始List并添加数据 List<Integer> originalList = new ArrayList<>(); originalList.add(1); originalList.add(2); originalList.add(3); // 使用Stream将原始List赋值到新的List List<Integer> newList = originalList.stream() .collect(Collectors.toList()); // 打印新的List System.out.println("新的List:" + newList); } } ``` 运行上述代码,将会输出以下结果: ``` 新的List:[1, 2, 3] ``` 通过使用Stream的`collect`方法,我们可以将原始List中的元素收集到新的List中。在上述示例中,我们使用`Collectors.toList()`来收集Stream中的元素到新的List。 ### 回答3: 在Java 8中,可以使用Stream API将一个List赋值到另一个List。具体的代码示例如下: ```java import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<Integer> sourceList = new ArrayList<>(); sourceList.add(1); sourceList.add(2); sourceList.add(3); List<Integer> targetList = sourceList.stream() .collect(Collectors.toList()); System.out.println("源列表: " + sourceList); System.out.println("目标列表: " + targetList); } } ``` 在上述代码中,我们首先创建了一个名为sourceListList,并向其中添加了一些元素。然后,使用Stream API的collect方法将sourceList的所有元素收集到一个新的List中,并将其赋值给targetList。targetList将包含与sourceList相同的元素。 运行上述代码,输出将会是: ``` 源列表: [1, 2, 3] 目标列表: [1, 2, 3] ``` 可以看到,targetList成功地赋值为sourceList的副本。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值