调用 List 中对象的 setter 方法也会更改 List 中其他对象的属性.列表是哈希映射中的值



我有一个包含键字符串和列表作为值的映射。将多个条目放入地图并随机展开地图中的列表值后,我遇到以下问题:

    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);
}

最新更新