如何创建一个不指另一个的Arraylist?

时间:2015-06-22 16:03:46

标签: java arraylist reference clone copy-constructor

我知道当你创建一个ArrayList并且在声明它时你将它引用到另一个ArrayList它只引用另一个,所以对第二个引起的更改改变了第一个。但是在面对这个问题时我感到困惑。

ArrayList <Productos> d3 = abd.dadesProductos();
ArrayList <Productos> dades2 = new ArrayList <Productos>();
System.out.println("before clear() + size= "+d3.get(i).configurables.size());//43
dades2.add(d3.get(i));
dades2.get(dades2.size()-1).configurables.clear();
System.out.println("after clear() + size= "+d3.get(i).configurables.size());//0

问题是,在从添加到dades2的最后一项中清除参数配置(另一个arraylist)后,它也会从d3中清除它,我根本不希望这种情况发生...为什么会发生这种情况我将该ArrayList创建为new ArrayList <Productos>();

我会提供任何帮助。

一些额外的信息。

我试图像这样创建一个新的构造函数:

Productos(Productos p)
    {
        this(p.entity_id, p.model, p.sku, p.name, p.weight, p.visibility, p.material, p.attribute_set_name, p.image, p.category_ids, p.category_ids2, p.color, p.color2, p.color3, p.cpsp_enable, p.created_at, p.description, p.colorswatch_disabled_category, p.colorswatch_disabled_product, p.msrp_display_actual_price_type, p.options_container, p.fcpm_enable, p.is_recurring, p.image_label, p.manage_stock, p.manufacturer, p.max_sale_qty, p.meta_description, p.meta_keyword, p.meta_title, p.category_positions, p.price, p.type_id, p.fcpm_second_attribute, p.fcpm_template, p.fcpm_template_position, p.short_description, p.fcpm_showfdd, p.fcpm_show_grandtotal, p.fcpm_second_layout, p.fcpm_show_link, p.fcpm_checkbox, p.fcpm_show_image, p.fcpm_show_rowtotal, p.fcpm_show_stock, p.special_price, p.special_from_date, p.special_to_date, p.status, p.tax_class_id, p.tier_price, p.url_key, p.updated_at, p.url_path, p.dimensions, p.mindeco, p.talla, p.trang1, p.trang2, p.trang3, p.trang4, p.trang5, p.tprice1, p.tprice2, p.tprice3, p.tprice4, p.tprice5, p.maxCols, p.marcPrio, p.configurables, p.marcajes);
    }

同样的想法发生了。我认为这是因为我通过引用分配了ArrayList配置。

我尝试用深度克隆做一些事但没有成功。根本不了解如何使用它。

dades2.add(new Productos(d3.get(i)));


Productos(Productos p)
    {
        this(p.entity_id, p.model, p.sku, p.name, p.weight, p.visibility, p.material, p.attribute_set_name, p.image, p.category_ids, p.category_ids2, p.color, p.color2, p.color3, p.cpsp_enable, p.created_at, p.description, p.colorswatch_disabled_category, p.colorswatch_disabled_product, p.msrp_display_actual_price_type, p.options_container, p.fcpm_enable, p.is_recurring, p.image_label, p.manage_stock, p.manufacturer, p.max_sale_qty, p.meta_description, p.meta_keyword, p.meta_title, p.category_positions, p.price, p.type_id, p.fcpm_second_attribute, p.fcpm_template, p.fcpm_template_position, p.short_description, p.fcpm_showfdd, p.fcpm_show_grandtotal, p.fcpm_second_layout, p.fcpm_show_link, p.fcpm_checkbox, p.fcpm_show_image, p.fcpm_show_rowtotal, p.fcpm_show_stock, p.special_price, p.special_from_date, p.special_to_date, p.status, p.tax_class_id, p.tier_price, p.url_key, p.updated_at, p.url_path, p.dimensions, p.mindeco, p.talla, p.trang1, p.trang2, p.trang3, p.trang4, p.trang5, p.tprice1, p.tprice2, p.tprice3, p.tprice4, p.tprice5, p.maxCols, p.marcPrio, p.marcajes);
        ArrayList <Configurable>configs=p.configurables;
        for(int i=0;i<configs.size();i++)
        {
            this.configurables.add(new Configurable(configs.get(i)));
        }
    }


Configurable(Configurable c)
    {
        this(c.codip, c.codic, c.sku, c.color, c.color2, c.color3, c.talla, c.price, c.image, c.trang1, c.trang2, c.trang3, c.trang4, c.trang5, c.tprice1, c.tprice2, c.tprice3, c.tprice4, c.tprice5);
    }

因为它似乎为Productos创建了一个新的构造函数,但我还为Configurable创建了一个新的构造函数,并在Productos上逐个复制项目构造函数。它现在似乎有效。

3 个答案:

答案 0 :(得分:5)

发生这种情况的原因是您要改变列表中的对象,而不是列表本身。这两个列表中都包含相同的对象,因此当您从一个列表中get()时,您也会获得另一个列表中包含的相同对象。

解决此问题的方法是将Productos类的副本插入新数组,而不是已创建的对象。根据Productos类的复杂程度,您可以创建一个复制构造函数,或在其上实现clone()来复制它。

答案 1 :(得分:2)

问题不是数组列表,而是你的任务:

dades2.add(d3.get(i));

您的对象需要实现某种类型的clone()函数,它们会创建一个填充了与原始实例相同数据的新实例。 所以上面的那一行应该成为

dades2.add( d3.get(i).clone() );

您可能想要研究的另一个主题是浅拷贝和深拷贝之间的区别。

答案 2 :(得分:0)

要创建ArrayList的独立副本,您需要迭代每个项目并单独克隆它们,然后将克隆放入新的ArrayList中。以下示例说明:

public static List<Productos> cloneList(List<Productos> list) {
    List<Productos> clone = new ArrayList<Productos>(list.size());
    for(Productos item: list) clone.add(item.clone());
    return clone;
}

要使上述方法起作用,您必须使您的Productos对象实现Cloneable接口并覆盖clone()方法。如果需要,您可以在此处阅读该流程:http://howtodoinjava.com/2012/11/08/a-guide-to-object-cloning-in-java/