Does the Java ArrayList.clear() method behave consistently?

107 Views Asked by At

Does the clear() method in Java null the elements in ArrayList or just free its references and keep values alive.

I am assigning all objects in ArrayList to another object and then clearings it. After clearing it the assigned references to another objects are giving inconsistent results. On the other hand if I create a new ArrayList object instead of clearing it works fine.

ArrayList <Condition> conditionList = new ArrayList<Condition>();    
Risk riskObject = new Risk();
for (int i =0; i<10; i++) {         
    if(some-condition){
                    addElemetsToConditionList();

                }else{
                    addElemetsToConditionList();            
                    riskObject.setConditions(conditionList); // Setter which sets condition list to risk object. 

                    Risk newRiskObject = new Risk();
                    riskObject = newRiskObject;

//                  conditionList = new ArrayList<Condition>();
                    conditionList.clear();

                }
            }
2

There are 2 best solutions below

1
On BEST ANSWER

Internally, it nulls all the elements in it's backing buffer (removing the references that it has) and set it's size to 0

/**
 * Removes all of the elements from this list.  The list will
 * be empty after this call returns.
 */
public void clear() {
    modCount++;

    // clear to let GC do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

Any references you might have to the data external are still valid, it's just the ArrayList no longer maintains a reference to them

I believe your problem is here...

riskObject.setConditions(conditionList);

You're passing the instance of the ArrayList to the riskObject and then clearing it, it is sharing the same instance.

Instead, you could create a new instance of a ArrayList

riskObject.setConditions(new ArrayList(conditionList));

Which makes a copy of the contents of the conditionList, so when you clear it, the reference you passed to riskObject won't be effected or, as you have already done, create a new ArrayList for your continuing processing, which ever seems most logical to you.

5
On

If riskObject.setConditions(conditionList); stores a reference to conditionList in the riskObject instance, calling conditionList.clear() would also clear the elements of the list reference held by the riskObject instance, since it refers to the same instance.

You can avoid it by creating a defensive copy :

public void setConditions (List<Condition> conditions)
{
    this.conditions = new ArrayList<> (conditions);
}

This is better than passing a copy of the List to the setConditions method of the Risk class, since it doesn't depend on the implementation of the code that uses the Risk class to function properly.