我有一个包含键字符串和列表作为值的映射。将多个条目放入地图并随机展开地图中的列表值后,我遇到以下问题:
list3 = map.get("string1");
list3.get(0).setName("testobject");
for(TestObject to : list3){
System.out.println(to.getName());
}
不仅将第一个测试对象设置为名称"testobject",它还将列表(list3)中的其他TestObjects设置为名称为"testobject",即:
**Output**
testobject
nonameset
nonameset
nonameset
testobject
nonameset
nonameset
nonameset
testobject
nonameset
下面写了完整的代码。我想这个问题与随机展开映射中的 List 值(randomlyExpand 函数)和引用有关,但由于我的 Java 知识仍在开始发展,我并不真正了解发生了什么。这可能是一件非常愚蠢的事情。所以我的问题是:这是怎么回事?以及如何在保留相同功能的同时解决问题。
import java.util.*;
public class Test {
public static void main(String[] args) {
Map<String, List<TestObject>> map = new HashMap<String, List<TestObject>>();
List<TestObject> list1 = new ArrayList<TestObject>();
List<TestObject> list2 = new ArrayList<TestObject>();
List<TestObject> list3 = new ArrayList<TestObject>();
for(int i = 0; i < 5; i++){
list1.add(new TestObject());
}
for(int i = 0; i < 5; i++){
list2.add(new TestObject());
}
map.put("string1", list1);
map.put("string2", list2);
map = randomlyExpand(map);
list3 = map.get("string1");
list3.get(0).setName("testobject");
for(TestObject to : list3){
System.out.println(to.getName());
}
}
//Randomly expand list values in Map from size 5 to size 10
public static Map<String, List<TestObject>> randomlyExpand(Map<String, List<TestObject>> map){
Random ran = new Random();
for (String key : map.keySet()){
List<TestObject> tempList = new ArrayList<TestObject>();
List<TestObject> values = map.get(key);
for (int i = 0; i < 10; i++){
int randomInt = ran.nextInt(values.size());
tempList.add(values.get(randomInt));
}
map.put(key, tempList);
}
return map;
}
}
测试对象类:
public class TestObject {
private String name = "nonameset";
TestObject(){
}
public String getName(){
return this.name;
}
public void setName(String s){
this.name = s;
}
}
在 randomlyExpand 方法中,您正在添加列表中已有的相同值。将新条目添加到列表中,但对象完全相同。
将对象添加到列表时,不会添加该对象的副本,而只是添加对该对象的引用。
这就是为什么当您更改其中一个条目中的属性时,它似乎在其他对象中反映了此更改。实际上,发生这种情况是因为您将同一对象多次添加到列表中。
问题出在您的randomlyExpand
函数中。您正在迭代您之前使用以下创建的 5 个可分辨对象的列表:
for(int i = 0; i < 5; i++){
list2.add(new TestObject());
}
现在你正在这样做:
int randomInt = ran.nextInt(values.size());
tempList.add(values.get(randomInt));
您正在获取此可分辨对象之一,并将其再次添加到另一个索引中。现在,这个单个对象在您的列表中出现两次(甚至更多次)。因此,您在列表中多次具有相同的对象。这是您多次看到或反对的方式。
解决方案很简单:在循环中创建新对象。
for (int i = 0; i < 10; i++){
int randomInt = ran.nextInt(values.size());
TestObject obj = new TestObject();
obj.setName(values.get(randomInt).getName());
tempList.add(obj);
}