【问题标题】:Copy object of ArrayList without Reference fast solution无引用复制ArrayList对象快速解决方案
【发布时间】:2019-07-22 14:14:29
【问题描述】:

我想做以下事情:

我有一个包含对象的列表,其中包含一个日期,现在我想不仅将这个对象用于一个日期,我还想设置日期并重用它们。选定列表包含 5 个元素。

while((stop.equals(countingDate)) || (countingDate.before(stop))) {
           
           for (c_TakeTimeObjects c_takeTimeObjects : SelectedList) {
               c_TakeTimeObjects addingObj = new c_TakeTimeObjects(1,1,"",true,this);
               
               c_takeTimeObjects.setsActivityDate(c_HelperClass_CalToStringDate.get(countingDate, 0, 0, 0));
               addingObj = c_takeTimeObjects;
               Log.i(TAG, "adjustDateRange: "+ addingObj.getsActivityDate());
               editList.add(addingObj);
           }
           countingDate.add(Calendar.DAY_OF_MONTH, +1);
       }

正如您可能猜到的那样,日志显示由循环引起的不同日期,但最终列表仅包含具有相同日期的元素。

log.i 给我:

    adjustDateRange: 25.06.2019
    adjustDateRange: 25.06.2019
    adjustDateRange: 25.06.2019
    adjustDateRange: 25.06.2019
    adjustDateRange: 25.06.2019
    adjustDateRange: 26.06.2019
    adjustDateRange: 26.06.2019
    adjustDateRange: 26.06.2019
    adjustDateRange: 26.06.2019
    adjustDateRange: 26.06.2019
    adjustDateRange: 27.06.2019
    adjustDateRange: 27.06.2019
    adjustDateRange: 27.06.2019
    adjustDateRange: 27.06.2019
    adjustDateRange: 27.06.2019
    adjustDateRange: 28.06.2019
    adjustDateRange: 28.06.2019
    adjustDateRange: 28.06.2019
    adjustDateRange: 28.06.2019
    adjustDateRange: 28.06.2019

并在添加所有对象后遍历列表给我:

for(c_TakeTimeObjects c_takeTimeObjects: editList){
            Log.i(TAG, "EditList: " + c_takeTimeObjects.getsActivityDate());
        }

    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019
    EditList: 28.06.2019

这是,因为我添加的对象之间存在引用,如何避免这种情况?也许一种解决方案是 DeepCopy,但这真的有必要吗?

更新

此代码产生相同的结果:

while((stop.equals(countingDate)) || (countingDate.before(stop))) {
           for (c_TakeTimeObjects c_takeTimeObjects : SelectedList) {
                c_takeTimeObjects.setsActivityDate(c_HelperClass_CalToStringDate.get(countingDate,0,0,0));
                Log.i(TAG, "adjustDateRange: "+ c_takeTimeObjects.getsActivityDate());
                editList.add(c_takeTimeObjects);
               
           }
           countingDate.add(Calendar.DAY_OF_MONTH, +1);
       }

【问题讨论】:

  • 您确定SelectedList 包含不同的对象而不仅仅是对单个对象的多个引用吗?请在编写代码时牢记 Java 代码指南。
  • SelectedList 包含 c_TakeTimeObjects 类的对象,它们都分配了不同的值。比如开始和停止时间或状态。在我的示例中 SelectedList 有 5 个对象。
  • 我添加了完整的 Log.i。 SelectedList 有 5 个元素

标签: android arraylist


【解决方案1】:

让我猜猜:你的 SelectedList 只包含 1 项,对吧?
其实通过做

addingObj = c_takeTimeObjects;

您总是用c_takeTimeObjects 替换您的addingObj 变量,所以最后,您向editList 添加了5 次相同的实例(c_takeTimeObjects)(甚至修改了SelectedList 的内容)
所以要么你创建一个新实例并手动复制你需要的属性

    for (c_TakeTimeObjects c_takeTimeObjects : SelectedList) {
        c_TakeTimeObjects addingObj = new c_TakeTimeObjects(1,1,"",true,this);
        addingObj.setsActivityDate(c_HelperClass_CalToStringDate.get(countingDate, 0, 0, 0));
// addingObj.setOtherAttribute1(c_takeTimeObjects.getOtherAttribute1);
// addingObj.setOtherAttribute2(c_takeTimeObjects.getOtherAttribute2);
        Log.i(TAG, "adjustDateRange: "+ addingObj.getsActivityDate());
        editList.add(addingObj);
    }

或者你实现 Cloneable 接口

    for (c_TakeTimeObjects c_takeTimeObjects : SelectedList) {
        c_TakeTimeObjects addingObj = (c_TakeTimeObjects) c_takeTimeObjects.clone();
        addingObj.setsActivityDate(c_HelperClass_CalToStringDate.get(countingDate, 0, 0, 0));
        Log.i(TAG, "adjustDateRange: "+ addingObj.getsActivityDate());
        editList.add(addingObj);
    }

编辑 假设您在 SelectedList 中的 5 个实例是 A、B、C、D、E
第一次迭代:使用

c_TakeTimeObjects addingObj = new c_TakeTimeObjects(1,1,"",true,this);

addingObj 是 F。然后用

addingObj = c_takeTimeObjects

addingObj 变为 A。
然后 addingObj.setsActivityDate(...) 将 2019-06-25 设置为 A,最后将 A 添加到 editList
第二次迭代:使用

c_TakeTimeObjects addingObj = new c_TakeTimeObjects(1,1,"",true,this);

,addObj就是G。然后用

addingObj = c_takeTimeObjects

addingObj 变为 B,然后 addingObj.setsActivityDate(...) 将 2019-06-25 设置为 B,最后将 B 添加到 editList
依此类推,直到 E。因此,A、B、C、D、E 的日期现在设置为 2019-06-25,并且 editList 包含 A、B、C、D、E。 F,G,H,I,J 没用过
在此之后,您再次从 2019-06-26 开始 -> A、B、C、D、E 的日期现在设置为 2019-06-26 并且 editList 包含 A、B、C、D、E、A、B ,C,D,E
然后将 2019-06-28 设置为 A,B,C,D,E 和包含 A,B,C,D,E,A,B,C,D,E,A,B,C 的 editList 结束, D、E、A、B、C、D、E。您使用new 创建的所有其他实例永远不会被使用和丢失。

【讨论】:

  • SelectedList在我的示例中有 5 项。
  • 所以我不明白 Log.i 如何显示不同的日期:在 for 循环之外增加了月份的日期
  • 增加的字段不是月份,而是月份中的某天。
  • 我已经编辑了我的评论,但这并没有改变countingDate 在循环中从未被修改过的事实
  • @oliver 应将月份中的日期分配给列表的所有元素,然后递增。在此之后,它应该再次分配给列表的所有元素,依此类推。
【解决方案2】:

尝试将这一行 c_TakeTimeObjects addingObj = new c_TakeTimeObjects(1,1,"",true,this); 移动到 for 之前 addingObj = c_takeTimeObjects;

编辑:

我不明白你的代码。但是你可以试试editList.add(c_takeTimeObjects);而不是editList.add(addingObj);

【讨论】:

  • 对不起,这是我一开始想发的。
  • 你可能会问自己为什么我制作了Object addedObj,因为我可以直接使用c_takeTimeObject。但我做了这个,因为我认为它可能有助于打破这两个对象之间的引用。
  • 是的,你是对的。我想知道c_HelperClass_CalToStringDate.get(countingDate,0,0,0)的结果是什么?
  • 我制作了这个助手,从日历值中获取字符串日期(格式 dd.MM.yy)。后面的 int 值只是您要从前面传递的 Calender 值中添加或减去的天数、月数或年数。
  • 好吧,让我们这样做:c_TakeTimeObjects addingObj = new c_TakeTimeObjects(1,1,"",true,this); addingObj.setsActivityDate(c_HelperClass_CalToStringDate.get(countingDate, 0, 0, 0));
【解决方案3】:

如果您使用的是 ArrayList,请记住,即使您将对象添加到另一个 ArrayList,两个数组也会引用同一个对象。

这意味着这个过程是这样的:

对于 while 循环的每次迭代,您都会迭代 for 循环,从而更改对象的属性。之后,您将它们添加到新的 ArrayList。当您进行下一次 while 迭代时,for 循环再次更改 THE SAME OBJECTS 的值,您再次将其添加到新的 ArrayList。

试试这个解决方法:

在 c_TakeTimeObjects 中生成一个构造函数,您可以在其中传递整个 c_TakeTimeObjects 对象,然后像这样编辑代码

editList.add(new c_TakeTimeObjects(c_takeTimeObjects ));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 2011-07-01
    • 2010-12-01
    相关资源
    最近更新 更多