如何创建一个不引用另一个的 Arraylist?
How can I create an Arraylist which not refers to another one?
我知道,当您创建一个 ArrayList 并声明它时,您将它引用到另一个 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 的最后一项中清除参数可配置项(另一个数组列表)后,它也会从 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
上逐一复制了项目构造函数。现在好像可以用了。
问题不是数组列表,而是您的作业:
dades2.add(d3.get(i));
您的对象需要实现某种类型的 clone()
函数,它们会创建一个新实例,其中填充了与原始实例相同的数据。
所以上面这行应该变成
dades2.add( d3.get(i).clone() );
您可能想进一步研究的主题是浅拷贝和深拷贝之间的区别。
发生这种情况的原因是您更改的是列表中的对象,而不是列表本身。这里的两个列表都包含相同的对象,因此当您从一个列表中 get()
时,您也会得到另一个列表中包含的相同对象。
解决此问题的方法是将 Productos
class 的副本插入新数组,而不是插入已创建的对象。根据您的 Productos class 的复杂性,您可以创建一个复制构造函数,或在其上实现 clone()
来复制它。
要创建 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/
我知道,当您创建一个 ArrayList 并声明它时,您将它引用到另一个 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 的最后一项中清除参数可配置项(另一个数组列表)后,它也会从 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
上逐一复制了项目构造函数。现在好像可以用了。
问题不是数组列表,而是您的作业:
dades2.add(d3.get(i));
您的对象需要实现某种类型的 clone()
函数,它们会创建一个新实例,其中填充了与原始实例相同的数据。
所以上面这行应该变成
dades2.add( d3.get(i).clone() );
您可能想进一步研究的主题是浅拷贝和深拷贝之间的区别。
发生这种情况的原因是您更改的是列表中的对象,而不是列表本身。这里的两个列表都包含相同的对象,因此当您从一个列表中 get()
时,您也会得到另一个列表中包含的相同对象。
解决此问题的方法是将 Productos
class 的副本插入新数组,而不是插入已创建的对象。根据您的 Productos class 的复杂性,您可以创建一个复制构造函数,或在其上实现 clone()
来复制它。
要创建 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/