2016-07-28 38 views
0

我正在处理映射中的列表插入操作,但无法理解插入行为。插入时的映射和列表值模糊性:java

public class TestList { 

public static void main(String[] args) { 

    String strarray[] = new String[5]; 

    for(int i = 0; i < 5; i++){ 

     strarray[i] = "Demo" + i; 
    } 

    Map<Integer, List<String>> cluesByText = new HashMap<Integer, List<String>>(); 
    int j = 0; 
    for (String str : strarray) { 

     System.out.println(str); 
     List<String> s = cluesByText.get(str); 
     if (s == null) { 
      s = new LinkedList<String>(); 
      cluesByText.put(j, s); 
     } 

     s.add(str); 
     s.add(str); 
     s.add(str); 
     s.remove(1); 
     // why it is storing without doing cluesByText.put(j,s); 
     j++; 
    } 

    //output is: 

    System.out.println(cluesByText); 

} 
} 

问题是,在做列表插入到地图,然后通过嵌件改变列表中的内容/删除操作,则得到反映在存储在地图中上一行 列表。

打印地图内容的最终输出是。

{0=[Demo0, Demo0], 1=[Demo1, Demo1], 2=[Demo2, Demo2], 3=[Demo3, Demo3], 4=[Demo4, Demo4]} 

我不能理解为什么它以这种方式发生,因为列表状态已经存储在地图中了?

+0

您插入的列表值仍然指向原始列表的值。 –

+1

与您的问题无关,但您的代码没有多大意义。 'cluesByText.get(str)'将总是返回null,因为你的Map的键是整数,而不是字符串。 – Eran

回答

0

您有一个对List<String>的引用,因此您可以将其添加到列表中。如果地图没有条目,则创建新的List<String>,并将条目添加到地图中。无论如何,List<String>的范围使其可用于工作。

1

这是预期的行为 - 您正在存储对地图列表的引用,而不是副本。在s中提到了相同的列表,因此如果通过s添加到列表中,它确实可以从map中看到 - 它只是对同一个对象的两个引用。

1

请记住,(几乎)Java中的所有内容都是参考,而不是值。所以,你所拥有的是从整数到列表的“地址”的映射,而不是列表的“状态”。

当你去学习存储在列表中的信息时,计算机会到那个地址看看那里有什么。

s设为该列表时,将该地址作为该地址存储在s中。

当您通过s.add()s.remove()对该列表进行更改时,它会转到该地址 - 与地图中的地址相同 - 并在其中进行更改。

因此,当您最终通过地图返回到该地址时,您正在查看相同的值。

这种情况没有发生的唯一情况是,当您将s=运算符分配时:然后,您实际上是将地址改写为另一个地址,因此查看原始地址的内容不受影响。