list集合循环添加对象防止对象重复和栈内存溢出

本文通过代码示例分析了在Java中使用List集合循环添加对象时出现对象重复的原因,并提供了两种解决方案。问题在于循环外实例化对象导致所有列表元素指向同一堆内存。推荐的解决方案是在循环外定义变量,循环内实例化对象,以避免栈空间浪费和对象重复。同时,对比了在循环内实例化对象可能导致的栈空间溢出问题。
摘要由CSDN通过智能技术生成

问题:list集合循环添加对象,添加完后遍历list集合发现,对象都一样,都是最后一个对象的值。
问题原因:在循环外实例化对象。

解决方法有两种:
1.循环外定义变量,循环内实例化对象赋值( 推荐!)
2.循环内定义变量并实例化对象

建议用第一种解决方法,理由:
第一种方法节省大量栈空间内存

package com.moon.test;

import java.util.ArrayList;
import java.util.List;

//list集合循环添加对象防止对象重复和栈内存溢出
//代码如下:
public class UserList {
	// 准备一个User类 只有一个id属性
	static class User {
		private String Id;

		public String getId() {
			return Id;
		}

		public void setId(String Id) {
			this.Id = Id;
		}

		public String toString() {
			return "User [Id=" + Id + "]";
		}
	}

	public static void main(String[] args) {
		// list1代码块 最后添加会出错【对象重复】
		{
			List<User> list1 = new ArrayList<>();
			// 添加出错原因,在for循环外实例化对象
			User user = new User();
			for (int i = 0; i < 3; i++) {
				user.setId("00" + i);
				list1.add(user);
			}
			System.out.println("list1:" + list1);
			System.out.println("");
		}

		// list2代码块 推荐的解决办法
		{
			List<User> list2 = new ArrayList<>();
			// 解决办法1:for循环外定义变量,循环内实例化对象
			User user = null;
			for (int i = 0; i < 3; i++) {
				user = new User();
				user.setId("0" + i);
				list2.add(user);
			}
			System.out.println("list2:" + list2);
			System.out.println("");
		}

		// list3 解决办法 不推荐哦
		{
			List<User> list3 = new ArrayList<>();
			for (int i = 0; i < 3; i++) {
				// 解决办法2:循环内实例化对象
				User t = new User();
				t.setId("0" + i);
				list3.add(t);
			}
			System.out.println("list3:" + list3);
		}
	}
}

打印结果:

从打印结果可以看出,list1都是指向同一个堆空间,自然都是一样的值

下面从虚拟机方面具体分析一下,
list1为什么会添加重复的对象
list2为什么会比list3节省大量栈空间

如图,我们每次实例化一个对象,如:User user = null; user = new User ();
User t = null;相当于在栈空间开辟一块内存存放引用地址【这个地址应该是十六进制的一串数字,此处用*代替】
t = new Teacher();相当于引用地址值指向堆空间中的实际值。

对于list1,当我在循环外实例化对象时,就是在栈空间开辟了一块名字为user 的内存,指向了堆空间的内存,此时堆空间内存存放值为null。然后,for循环为堆空间内存中的对象赋值,每次循环相当于user 指向堆空间。而list集合每次添加的只是对象的引用值,而非堆空间的实际值,所以,每次循环添加的都是栈空间的引用地址值,都是同一个对象,最后一次循环确定了这个对象的值。这就是list集合循环添加对象出现对象重复的根本原因。

对于list3,对象的实例化放在了循环里面,于是,每次循环都会在栈空间重新开辟一块内存空间,循环了多少次,就开辟了多少次空间,显然很浪费,还可能会导致栈空间内存溢出。

所以建议使用list2,将开辟栈空间内存放在循环外面,每次循环只是重新指向一个新的值。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值