简体   繁体   中英

How can I create an Arraylist which not refers to another one?

I know that when you create an ArrayList and when declaring it you refer it to another ArrayList it only refers to the other so changes made to the second one change the first one. But I got confused when facing this problem.

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

The problem is that after clearing the parameter configurables(another arraylist) from the last item added to dades2 it also clears it from d3 which I don't want this to happen at all... Why is this happening if I create a that ArrayList as new ArrayList <Productos>();

I will appreaciate any help.

Some extra information.

I have tried to create a new Constructor like this:

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);
    }

And same think happens. I think it's because I assign the ArrayList configurables by reference.

I've tried to do something with deep clone with no success. Don't understand how to use it at all.

SOLUTION

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);
    }

As it seemed creating a new constructor for Productos wasn't enough I also created a new constructor for Configurable and copying the items with a for one by one on Productos constructor. It seems it works now.

The reason this is happening is that you're altering the object in the List, not the List itself. Both Lists here contain the same object within them, so when you get() from one, you're getting the same object contained within the other List too.

The way to get around this is to insert a copy of your Productos class into the new array, instead of the already created object. Depending on the complexity of your Productos class, you can create a copy constructor, or implement clone() on it to copy it.

The issues is not the array list, but your assignment:

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

Your objects need to implement some type of clone() function where they create a new instance filled with the same data as the original one. So the line above should become

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

A further topic you may want to research is the difference then between shallow copy and deep copy.

To create an independent copy of your ArrayList, you need to iterate on each of the items and clone them individually, putting the clones into your new ArrayList as you go. Here is an example demonstrating:

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;
}

For the above method to work you have to make your Productos object implement the Cloneable interface and overwrite the clone() method. If need be, you can read up on that process here: http://howtodoinjava.com/2012/11/08/a-guide-to-object-cloning-in-java/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM