我从Goetz的书(Java Concurrency in Practice)中获得了以下代码。
这本书说将ConcurrentMap作为Collections.unmodifiableMap中的参数传递,将给出位置的“实时”视图(即,调用下面的getLocations()),这意味着对setLocation的调用将反映给调用者。
但是,将HashMap作为Collections.unmodifiableMap中的参数传递将给出位置的原始视图(静态视图)(即,在下面调用getLocationsAsStatic())
有人会解释背后的原因吗?谢谢
@ThreadSafe
public class DelegatingVehicleTracker {
private final ConcurrentMap<String, Point> locations;
private final Map<String, Point> unmodifiableMap;
public DelegatingVehicleTracker(Map<String, Point> points) {
locations = new ConcurrentHashMap<String, Point>(points);
unmodifiableMap = Collections.unmodifiableMap(locations);
}
public Map<String, Point> getLocations() {
return unmodifiableMap;
}
public Point getLocation(String id) {
return locations.get(id);
}
public void setLocation(String id, int x, int y) {
if (locations.replace(id, new Point(x, y)) == null)
throw new IllegalArgumentException("invalid vehicle name: " + id);
}
// Alternate version of getLocations (Listing 4.8)
public Map<String, Point> getLocationsAsStatic() {
return Collections.unmodifiableMap(
new HashMap<String, Point>(locations));
}
}
@Immutable
public class Point {
public final int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
答案 0 :(得分:1)
行为上的差异不是由于地图的类型不同,而是地图的创建方式。 Collections.unmodifiableMap
只会包装给定的地图。
您的ConcurrentMap<String, Point> locations
是您要修改的地图,因此,在包装它时,使用不可修改的地图时,您仍然会看到最新的值。
不过,您的HashMap
是使用new HashMap<String, Point>(locations)
创建的。 this constructor的文档说:
使用与指定Map相同的映射构造一个新的HashMap。
参数:
m-要在其地图中放置其映射的地图
因此它实际上将给定映射的所有条目复制到新创建的映射中。因此,此新地图与locations
地图不再相关。