Lists.addAll(Map.get(key)), 无意中改变了`Map`

Lists.addAll(Map.get(key)), unintentionally changes the`Map`

MapConstants.java:包含四个MapsMAP1是ReversedMap,MAP2是ReverseMap。 ReverseMap 是按照 answer

创建的
import com.google.common.collect.ImmutableMap;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MapConstants {

    public static final ImmutableMap<String, String> MAP1 = ImmutableMap.<String, String>builder()
            .put("FD1", "FDG")
            .build();

    public static final Map<String, List<String>> REVERSE_MAP1 =
            MAP1.entrySet()
                    .stream()
                    .collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())));


    public static final ImmutableMap<String, String> MAP2 = ImmutableMap.<String, String>builder()
            .put("FD2", "FDG")
            .build();

    public static final Map<String, List<String>> REVERSE_MAP2 =
            MAP2.entrySet()
                    .stream()
                    .collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())));

}

我使用 addAll() 方法从 反向 Map 添加相同的键到新列表 exampleList

可重现的例子 - 不是我面对的确切例子,我们不使用 psvm 但这是如何重现它的很好的表示。

import ..REVERSE_MAP1;
import ..REVERSE_MAP2;

public class Test {

    public void main(String[] args){

        System.out.println("REVERSE_MAP1 BEFORE list.addAll" + REVERSE_MAP1);
        //Returns {FDG=[FD1]}

        final List<String> exampleList = REVERSE_MAP1.get("FDG");
        exampleList.addAll(REVERSE_MAP2.get("FDG"));

        System.out.println("REVERSE_MAP1 AFTER list.addAll" + REVERSE_MAP1);
        //Returns {FDG=[FD1, FD2]}
        
    }
} 

为什么当我尝试 addAll()exampleList 时,REVERSE_MAP1 的列表具有 REVERSE_MAP2 的值?我的期望是只有 exampleList 应该改变,而不是 REVERSE_MAP1FDG 键的值。

抱歉,如果您无法重现它,我们将代码部署在 AWS 上,所以我没有费心用 psvm 创建一个新项目,就像我在上面复制粘贴的那样,因为当我现有的调用我们方法的 运行 UTC 时,我的打印语句显示 Map 似乎正在改变。

这一行:

final List<String> exampleList = REVERSE_MAP1.get("FDG");

获取对 REVERSE_MAP_1 中包含的列表的引用。这不是一个新对象。它仍然是 REVERSE_MAP_1 中的同一个对象。所以当你打电话时:

exampleList.addAll(REVERSE_MAP2.get("FDG"));

您实际上是在向 REVERSE_MAP_1 中的列表对象添加更多数据。如果您想要一个包含来自 REVERSE_MAP_1 和 REVERSE_MAP_2 的数据的新列表而不更改其中任何一个地图中的数据,则需要创建一个新列表。

final List<String> exampleList = new ArrayList<>();
exampleList.addAll(REVERSE_MAP1.get("FDG"));
exampleList.addAll(REVERSE_MAP2.get("FDG"));

编辑:

我不认为你的反向映射是不可变的。但即使它们是,反向映射中包含的 List 对象也绝对不是不可变的。正如您的示例所证明的那样,您可以轻松地从存储在反向映射中的列表中添加(或删除)数据。