Reputation: 1111
Why does .clear()
destroy my object list even after being put in a hashmap as opposed to just making a new instance of that object?
Variable Declarions:
List<Pricing_Data> toAdd = new ArrayList<Pricing_Data>();
HashMap<String, List<Pricing_Data>> pricingMap_twelve = new HashMap<String, List<Pricing_Data>>();
Example working as expected:
pricingMap_twelve.put(pricing.get(y).getName(), toAdd);
toAdd = new ArrayList<Pricing_Data>();
Example unexepected destruction of data in hashmap after being added to said hashmap:
pricingMap_twelve.put(pricing.get(y).getName(), toAdd);
toAdd.clear();
I'm guessing this has to do with a similar issue where I ran into when first messing around with calendars where the data isn't actually 'put' into the object but is instead a pointer to the original?
Upvotes: 0
Views: 1054
Reputation: 181932
Java variables of non-primitive type hold references to objects. Passing references around and assigning them to other variables, arrays, etc. affects only the reference, not the object to which it refers. Although it's common, it's also loose and sometimes confusing to say that a variable "contains" an object.
Therefore, when you use Map.put()
you enroll in your map references to the specified key and value; references stored in other places, such as variable toAdd
, still refer to the same object.
Naturally, after you assign a reference to a new object to a variable, that variable is no longer associated with the object it previously referred to.
Upvotes: 1
Reputation: 727137
Strictly speaking, there are no pointers in Java, but references behave in much the same way: if you add a reference object to a collection, and then change that object, the item stored in the collection is going to change as well. In particular, when you call clear
, the result is going to be visible through all references of the collection, including any references that you may have placed in other collections.
A useful corollary here is that if you are adding collections into another container, you nearly always want to make a new copy, not the container itself, into the collection. This lets you avoid a common mistake:
List<List<String>> sentences = new ArrayList<List<String>>();
List<String> words = new ArrayList<String>();
// This is broken!
while (haveMoreData(myFile)) {
readNextSentence(myFile, words);
sentences.add(words);
words.clear();
}
The above code is wrong, because it attempts to put the same list words
into sentences
multiple times, clearing it in between. You end up with multiple instances of the last sentence in the list.
Using new
fixes the problem:
List<List<String>> sentences = new ArrayList<List<String>>();
while (haveMoreData(myFile)) {
List<String> words = new ArrayList<String>();
readNextSentence(myFile, words);
sentences.add(words);
}
Now each iteration gets its own container for words
, avoiding the aliasing issue that resulted from reusing and clearing the same collection.
Upvotes: 1
Reputation: 34648
That's the definition of clear
. It is not the same as new
. new
creates a new objects and gives you a reference to the new object. The method clear
of a given object takes that same object and erases what's inside it.
It's important to understand that putting an object in a list does not put a copy of the object in a list. It puts a reference to that object in the list. The reference you have in the variable and the reference you have inside the list are pointing to the same object so if you clear it, the list is also pointing to the cleared object.
So you have to use new
, not clear
.
Upvotes: 2
Reputation: 85809
When using toAdd.clear
method, you will clear the contents of the current reference of the list hold by toAdd
variable.
When using toAdd = new ArrayList<Pricing_Data>()
, now toAdd
variable points to a new reference. The old reference holded by toAdd
will still be stored in the reference hold by pricingMap_twelve
.
More info:
Upvotes: 2