Reputation: 243
I have a HashMap as follows,
Map<String, MyClass> testMap = new HashMap<>();
map.put("1", myClass1);
map.put("2", myClass2);
Here MyClass
is a bean class. Now I wish to get a value of testMap
, and change the value without changing the testMap
itself. What I did is as follows,
MyClass result = testMap.get("1");
if (some conditions){
do someting to result;
}
return result;
What I expect is that result
changes and testMap
keeps unchanged. But actually myClass1
in testMap
changes as well. So how can I achieve my goal?
Upvotes: 1
Views: 993
Reputation: 193
You'll need to make a copy of MyClass. If you have references to objects within, you'll need a deep copy.
Within the map, it stores references to the objects. So when you get the reference to that object from the map and modify it, you're modifying the same instance of the object. If you make a copy, you'll be able to make changes to one, but not the other.
Shallow Copying vs. Deep Copying
Shallow copying can be done with .clone(), but just copies all of the fields, and if there are objects as fields in the class, only the reference will be copied. This is problematic because you'll have the same copies of the internal objects within each copy, and you'll end up with the same situation as above - when you modify any of those objects, you'll modify the other ones too.
Deep copying alleviates this problem, as it copies internal objects as well. You can go through and recursively copy, copy through serialization, or external libraries (like Apache Commons Lang SerializationUtils.clone()). This link has some more details if you're curious. https://www.baeldung.com/java-deep-copy
Upvotes: 0
Reputation: 720
Immutable Implementation of MyClass:
public class MyClass {
private final String name;
public MyClass(String name) {
this.name = name;
}
/**
* @return the name
*/
public String getName() {
return name;
}
}
Client to verify Immutability:
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
MyClass myClass = new MyClass("class1");
System.out.println("Object " + myClass);
Map<Integer, MyClass> map = new HashMap<Integer, MyClass>();
map.put(1, myClass);
MyClass result = map.get(1);
System.out.println("From Map Object " + result);
String name = result.getName();
if (name != null && name.equals("class1")) {
MyClass updatedResult = new MyClass("updatedclass1 ");
System.out.println("Updated Object " + updatedResult);
}
System.out.println("From Map Object " + result);
}
}
Output:
Object MyClass@6d06d69c
From Map Object MyClass@6d06d69c
Updated Object MyClass@7852e922
From Map Object MyClass@6d06d69c
After update map remain same.
Upvotes: 0
Reputation: 1958
It can be achieved by creating immutable object. When you change the value of this object it will always create a new object and will not change original value.
Upvotes: 0
Reputation: 18123
There are multiple ways to achieve that:
testMap
you first manually copy it into a new object of the same type. In C++ this was commonly implemented using a copy constructor: new MyClass1(myClass);
where the copy constructor takes all fields of the object passed in and copies it into a new object, in Java this is sometimes done using the Cloneable
interface.BigDecimal
where every operation on a BigDecimal
object always returns a new BigDecimal
object.Upvotes: 1