为啥在一个 ArrayList 中改变一个对象会在所有其他 ArrayList 中改变它?

Posted

技术标签:

【中文标题】为啥在一个 ArrayList 中改变一个对象会在所有其他 ArrayList 中改变它?【英文标题】:Why does mutating an object in one ArrayList change it in all other ArrayLists?为什么在一个 ArrayList 中改变一个对象会在所有其他 ArrayList 中改变它? 【发布时间】:2015-08-12 18:14:12 【问题描述】:

我正在制作一个 cpu 调度模拟器(用于学校项目)。我的roundRobin 函数有问题。当我执行c.get(i).jobTime -= 2;c.get(i).jobTime -= 1; 时,它会影响我的其他ArrayLists,因此我无法执行其他功能。在我打电话给roundRobin2 之前,我的名单是完全正常的。为什么会这样?

例如,这是我的list4roundRobin2 之后的样子

list 4: [Job101 0, Job102 0, Job103 0, Job104 0, Job105 0, Job106 0]

这就是我在文件中读取的方式,并将Jobs 对象放入我的ArrayLists 中。

Scanner input = new Scanner(new File("testdata1.txt"));
ArrayList<Jobs> list = new ArrayList<Jobs>();
ArrayList<Jobs> list2 = new ArrayList<Jobs>();
ArrayList<Jobs> list3 = new ArrayList<Jobs>();
ArrayList<Jobs> list4 = new ArrayList<Jobs>();

Jobs first;

while (input.hasNext()) 
    first = new Jobs(input.next(), input.nextInt());
    list.add(first);
    list2.add(first);
    list3.add(first);
    list4.add(first);


input.close();

这是我的roundRobin2

public void roundRobin2(ArrayList<Jobs> c, int sT) 
    int size = c.size();
    int cT = 0;
    int ccT = 0;
    while (!c.isEmpty()) 
        int i = 0;
        System.out.println(c);
        for (i = 0; i < size; i++) 
            if ((c.get(i).jobTime) >= 2) 
                c.get(i).jobTime -= 2;
                cT += 2;

                if ((c.get(i).jobTime) == 0) 
                    ccT += cT;
                
             else 
                (c.get(i).jobTime) -= 1;
                cT += 1;

                if ((c.get(i).jobTime) == 0) 
                    ccT += cT;
                
            
        
        for (i = 0; i < size; i++) 
            if ((c.get(i).jobTime) == 0) 
                c.remove(i);
                size = c.size();
            
        
    
    System.out.println("\nAverage completion times: "+ccT+"/"+sT+" = "+((ccT)/sT));

【问题讨论】:

【参考方案1】:

在每次迭代中,您只创建一个对象并将其添加到所有 4 个列表中。当你改变那个对象时,好吧,改变它。该突变将反映在所有列表中,因为它们都存储相同的对象引用。

while (input.hasNext()) 
    first = new Jobs(input.next(), input.nextInt());
    list.add(first);
    list2.add(first);
    list3.add(first);
    list4.add(first);

相反,您需要为每个列表添加一个新的对象引用(如果您希望将对象的克隆存储在每个列表中)。

while (input.hasNext()) 
    String s = input.next();
    int i = input.nextInt();
    list.add(new Jobs(s, i));
    list2.add(new Jobs(s, i));
    list3.add(new Jobs(s, i));
    list4.add(new Jobs(s, i));

在第一个代码示例中,list.get(n) == list2.get(n) 将是 true(对于任何有效的 n 和您的 4 中的任何两个列表都是如此)。在第二个示例中,它将是 false,因为您现在拥有完全不相关的对象,这些对象恰好在它们添加到列表时存储了相同的值。

【讨论】:

谢谢@AndyBrown,当我阅读您的评论时,我知道您刚刚添加的内容正是如此。我不敢相信我以前没有想到这一点

以上是关于为啥在一个 ArrayList 中改变一个对象会在所有其他 ArrayList 中改变它?的主要内容,如果未能解决你的问题,请参考以下文章

当您在不指定对象类型的情况下创建 ArrayList 时,它会在您添加第一个对象时自动创建它吗?

java代码中Collection c = new ArrayList 为啥说比ArrayList c = new ArrayListy用法灵活?

为啥通过 python 默认变量初始化变量会在对象实例化过程中保持状态?

数组对象与ArrayList

数组对象与ArrayList

为啥是List list = new ArrayList,而不直接用ArrayList