0

我有一个包含键的字符串和作为值的列表的 Map。在将几个条目放入 Map 并随机扩展 Map 中的 List 值后,我遇到以下问题:

    list3 = map.get("string1");
    list3.get(0).setName("testobject");
    for(TestObject to : list3){
        System.out.println(to.getName());
    }

它不仅设置名称为“testobject”的第一个TestObject,还设置列表(list3)中名称为“testobject”的其他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;
}
}
4

2 回答 2

4

在您的 randomExpand 方法中,您将添加列表中已有的相同值。您将新条目添加到列表中,但对象完全相同。

当您将对象添加到列表时,您不会添加该对象的副本,而只是添加对它的引用。

这就是为什么当您更改其中一个条目中的属性时,它似乎反映了其他对象中的这种更改。实际上,发生这种情况是因为您将同一个对象多次添加到列表中。

于 2012-05-01T15:22:16.327 回答
3

问题出在你的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);
}
于 2012-05-01T15:24:03.060 回答