Reputation: 745
I am having a problem with the references of objects in Java. Here's the situation.
Let's say I have an object class called MyObject.
class MyObject {
Long id;
String item;
Integer number;
BigDecimal bigNumber;
//and Some getter and setter methods
}
Let's also say I have hashmap:
HashMap<Long, MyObject> myHash = new HashMap<Long, MyObject>();
and I fill this hashmap with some objects of MyObject.
Then when I try to copy all elements of this hashmap to an arrayList (with addAll method), all the objects which are included in hashmap are copied to the arraylist with the same references. For this reason, when I try to change an MyObject object in hashmap, it also changes in arrayList too. I don't want that. How do I prevent that?
I hope that I clearly tell the problem.
Thanks in advance.
Upvotes: 1
Views: 3008
Reputation: 709
I would make the class MyObject
cloneable by implementing the Cloneable
interface, see Cloneable Javadoc.
Java copies references and not objects. It's important to learn and understand this. In your case you want to copy objects, so you must implement a method which goes through the map, copies your objects, and places references to these copies into the array.
If you need some more information about cloning in Java, this Wikipedia page is a good source.
The solution could look like this:
Make class MyObject
cloneable by implementing the Cloneable
interface. Object
has a default implementation of method clone()
which copies all fields. In your case you have Long
, String
, Integer
, and BigDecimal
fields. All of them are immutable, so they don't need to be cloned themselves and that's why you don't need to do anything in the clone()
method of your class. You still need to override Object.clone()
in order to make it public. You would need to add code to clone()
if one of your fields referenced another object which required cloning.
class MyObject implements Cloneable {
Long id;
String item;
Integer number;
BigDecimal bigNumber;
//and Some getter and setter methods
@Override
public MyObject clone() throws CloneNotSupportedException {
return (MyObject)super.clone();
}
}
Write a method for copying objects from your map into an array:
public ArrayList<MyObject> getArray() {
ArrayList<MyObject> list = new ArrayList<MyObject>(myHash.size());
for(MyObject object : myHash)
list.add(object.clone());
}
Upvotes: 1
Reputation: 432
you need to clone/copy MyObject before you add them to arraylist. When you use addAll only the object references are copied from source collection to target collection, objects themselves are not.
ArrayList copyTo = new ArrayList()
for( MyObject current : myHash.values() )
{
copyTo.add(copy(current));
}
MyObject copy(MyObject o)
{
MyObject copyObj = new MyObject();
// set attributes here from 'o' to 'copyObj'
return copyObj;
}
Upvotes: 0
Reputation: 133587
You should create a copy of your data and then use the copy with the list:
class MyObject {
..
public MyObject dupe() {
return new MyObject(id, item, number, bigNumber, ..);
}
}
void createList() {
ArrayList<MyObject> list = new ArrayList<MyObject>();
for (Map.Entry<Long, MyObject> e : map.entries())
list.add(e.getValue().dupe());
}
Upvotes: 0
Reputation: 533530
Currently you are just copying the references. This is done because copying the objects is pretty expensive.
In your case you want to copy the objects, so you will need to copy each one as you add them to the list. Something like
for(MyObject mo: myHash.values())
list.add(mo.copy());
You can implement copy in any number of ways, including using clone();
Upvotes: 1