为什么要修改Arraylist副本,修改原始文件?

时间:2016-06-17 12:05:27

标签: java arraylist cloneable

我正在尝试将ArrayList的内容复制到另一个并更改复制的内容。我不希望这一点反映在原文中。

我检查了SO并做了相应的更改,仍然是同样的问题。有人可以帮忙吗?我正在分享以下代码:

private ArrayList<CustVoiceListObject> FilterApprovedWorkFromList() {

        ArrayList<CustVoiceListObject> arrayListCopy = new ArrayList<>(arrayListCustVoice);

            for(int i =0; i<arrayListCopy.get(position).getPackageArray().size();i++)
            {
                if(!arrayListCopy.get(position).getPackageArray().get(i).getPackageApproved().equals("Y"))
                {
                    arrayListCopy.get(position).getPackageArray().remove(i);
                    i--;
                }
            }
        return arrayListCopy;
    }

在调试时,当它即将返回时,我会检查原始的arraylist arrayListCustVoice,但这也会被修改为arrayListCopy

我错过了什么?

更新 [遵循建议] [此问题因此不重复!]

这是我修改后的代码:

 private ArrayList<CustVoiceListObject> FilterApprovedWorkFromList() {

        ArrayList<CustVoiceListObject> arrayListCopy = (ArrayList<CustVoiceListObject>) arrayListCustVoice.clone();

            for(int i =0; i<arrayListCopy.get(position).getPackageArray().size();i++)
            {
                if(!arrayListCopy.get(position).getPackageArray().get(i).getPackageApproved().equals("Y"))
                {
                    arrayListCopy.get(position).getPackageArray().remove(i);
                    i--;
                }
            }
        return arrayListCopy;
    }

事实上我已经将Cloneable实现到我原来的类中,但我仍面临同样的问题。

更新2 [研究结论]

我遇到了这个link

就我而言,有2个班级。第二个是第一个子集。粘贴在下面:

public class CustVoiceListObject implements Cloneable {

    private String txtSource, txtCustComment, txtCustOk, txtRepeat;

    private int numberOfPackages, complaintSerial;

    private ArrayList<CustomerVoicePackageListObject> packageArray;

    private Double totalAmount;

   //getters & setters & constructors

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }


}

第2课:

public class CustomerVoicePackageListObject implements Cloneable {

    public String packageCategory;
    public String packageName;
    public String partUsageFlag;
    public String laborUsageFlag;
    public String status;
    public String isApproved;

 //getters & setters & constructors

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}

.clone()必须链接到CLASS的clone(),而不是其他地方。如果它正确的话,它将引发采取措施来解决异常,因为我在每个单独的类中实现了clone()。

所以这就是我所做的,将其修改为循环:

 private CustVoiceListObject FilterApprovedWorkFromList() {

//Observe the change here. It's no more ArrayList, it's Class type
        CustVoiceListObject arrayListCopy = null;
        try {
            arrayListCopy = (CustVoiceListObject) arrayListCustVoice.get(position).clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        for(int i =0; i<arrayListCopy.getPackageArray().size();i++)
            {
                if(!arrayListCopy.getPackageArray().get(i).getPackageApproved().equals("Y"))
                {
                    arrayListCopy.getPackageArray().remove(i); //this is ArrayList<ClassType>. Nested class objects.
                    arrayListCopy.setTxtCustOk("OKOK"); //within the class
                    i--;
                }
            }
        return arrayListCopy;
    }

结果是packageArray中的更改反映在(失败)BUT,基本类中的txtCustOk的更改,副本中的更改,而不是原始(成功)中。这意味着,问题在于使用ArrayList进行克隆

如此深入的克隆需要满足以下规则:

  

1.无需单独复制基元。

     

2.原始类中的所有成员类都应该支持克隆,并且在上下文中应该调用原始类的克隆方法   所有成员类上的super.clone()。

     

3.如果任何成员类不支持克隆,那么在克隆方法中,必须创建该成员类的新实例并复制其全部   属性逐个归属到新成员类对象。这个新成员   类对象将在克隆对象中设置。

所以我的目标是摆脱ArrayList并将这些元素转移到这个类。这很痛苦。寻找一个简单的替代方案。

2 个答案:

答案 0 :(得分:1)

问题是原始ArrayList的元素是引用值,因此您只需复制对这些对象的引用,而不是对象本身(它们似乎是另一种数组)。

查看基本上处理同类问题的this问题。

答案 1 :(得分:0)

复制操作复制了原始列表 - 但不复制列表中的元素。

也就是说,如果oldList有以下Person个对象:

  

oldListJohnJaneJudeJoe

您已将oldList复制到newList

  

oldListJohnJaneJudeJoe
  newListJohnJaneJudeJoe

然后从John

中删除了newList
  

oldListJohnJaneJudeJoe
  newListJaneJudeJoe

你可以看到它们是两个不同的列表。但是您更改列表,您正在更改列表中 内的对象。如果Joe的名称已更改为Jim,则您需要:

  

oldListJohnJaneJudeJim
  newListJaneJudeJim

你只做了所谓的“浅”副本。您想要执行“深层”复制,如here所示。

修改(至相关的“更新2”)

你的研究还远远不够,我很害怕。在你的(新)第1课:

public class CustVoiceListObject implements Cloneable {

    // ints, Doubles, Strings

    private ArrayList<CustomerVoicePackageListObject> packageArray;

    //getters & setters & constructors

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

您只需返回super.clone() - 让Java为您完成所有工作。这基本上做了导致你所有问题的浅拷贝!您可能还没有制作对象ICloneable。您错过的是int s,Double甚至String已成功复制,因此您无需克隆它们。但是ArrayList s 没有克隆,所以你需要帮助它:

@Override
protected Object clone() throws CloneNotSupportedException {
    // First copy the easy stuff
    CustomerVoiceListObject cvlo = (CustomerVoiceListObject)super.clone();

    cvlo.packageArray = new ArrayList<CustomerVoicePackageListObject>(packageArray.size()); // Make sure it's the right size

    for (CustomerVoicePackageListObject cvplo: packageArray) {
        cvlo.packageArray.add(cvplo.clone());
    } // for
    return cvlo;
} // clone()