英文:
How to get and change a value of a hashmap, without changing the hashmap itself in Java?
问题
我有一个如下的HashMap,
Map<String, MyClass> testMap = new HashMap<>();
map.put("1", myClass1);
map.put("2", myClass2);
这里MyClass
是一个JavaBean类。现在我希望获取testMap
的一个值,并且在不改变testMap
本身的情况下修改这个值。我所做的操作如下,
MyClass result = testMap.get("1");
if (一些条件){
对result进行操作;
}
return result;
我期望的是result
改变,而testMap
保持不变。但实际上,testMap
中的myClass1
也发生了改变。那么我该如何实现我的目标呢?
英文:
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?
答案1
得分: 1
有多种方法可以实现这个:
- 当你从
testMap
中取出一个对象时,首先要手动将它复制到一个相同类型的新对象中。在C++中,这通常是使用复制构造函数实现的:new MyClass1(myClass);
,其中复制构造函数接受传入对象的所有字段,并将其复制到一个新对象中;在Java中,有时会使用Cloneable
接口来实现这一点。 - 使你的对象不可变,这样对象上的更改永远不会改变其状态,而是始终返回一个包含这些更改的新对象。一个相对较新的示例是
BigDecimal
,在BigDecimal
对象上的每个操作始终返回一个新的BigDecimal
对象。
英文:
There are multiple ways to achieve that:
- When you take an object out of
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 theCloneable
interface. - Make your object immutable so that a change on an object never changes its state but always returns a new object that incorporates those changes. A relatively new example is
BigDecimal
where every operation on aBigDecimal
object always returns a newBigDecimal
object.
答案2
得分: 0
这可以通过创建不可变对象来实现。当您更改此对象的值时,它将始终创建一个新对象,而不会更改原始值。
英文:
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.
答案3
得分: 0
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.
英文:
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.
答案4
得分: 0
你需要复制我的MyClass。
如果你在其中有对象的引用,你会需要进行深拷贝。
在这个映射内部,它存储了对这些对象的引用。因此,当你从映射中获取对该对象的引用并进行修改时,你实际上是修改了同一个对象的实例。如果你进行复制,你将能够对一个副本进行更改,但另一个副本不会受影响。
浅拷贝与深拷贝
浅拷贝 可以使用 .clone() 方法来实现,但它只会拷贝所有字段,如果类中的字段是对象,那么只会拷贝引用。这是有问题的,因为在每个拷贝中你都将拥有相同的内部对象副本,从而出现与上述相同的情况 - 当你修改任何一个对象时,另一个对象也会被修改。
深拷贝 解决了这个问题,因为它也会拷贝内部对象。
你可以通过递归拷贝、通过序列化进行拷贝,或者使用外部库(比如 Apache Commons Lang 的 SerializationUtils.clone() 方法)。如果你感兴趣,这个链接提供了更多细节。
https://www.baeldung.com/java-deep-copy
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论