Lists.addAll(Map.get(key)), 无意中改变了`Map`
Lists.addAll(Map.get(key)), unintentionally changes the`Map`
MapConstants.java
:包含四个Maps
:MAP1
是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_MAP1
的 FDG
键的值。
抱歉,如果您无法重现它,我们将代码部署在 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 对象也绝对不是不可变的。正如您的示例所证明的那样,您可以轻松地从存储在反向映射中的列表中添加(或删除)数据。
MapConstants.java
:包含四个Maps
:MAP1
是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_MAP1
的 FDG
键的值。
抱歉,如果您无法重现它,我们将代码部署在 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 对象也绝对不是不可变的。正如您的示例所证明的那样,您可以轻松地从存储在反向映射中的列表中添加(或删除)数据。