Используйте Collections.unmodifiableMap с ConcurrentHashMap / HashMap в качестве параметра - PullRequest
0 голосов
/ 26 января 2019

Я получил следующий код из книги Гетца (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;
    }
}

1 Ответ

0 голосов
/ 03 мая 2019

Различие в поведении связано не с разными типами карт, а с тем, как они создаются. Collections.unmodifiableMap просто оборачивает данную карту.

Ваша ConcurrentMap<String, Point> locations - это карта, которую вы изменяете, поэтому, когда вы ее оборачиваете, вы все равно увидите обновленные значения при использовании неизменяемой карты.

Однако ваш HashMap создан с использованием new HashMap<String, Point>(locations). Документация для этого конструктора гласит:

Создает новую HashMap с теми же отображениями, что и указанная карта.

Параметры:
m - карта, отображения которой должны быть размещены на этой карте

Таким образом, он фактически копирует все записи данной карты во вновь созданную. Поэтому эта новая карта больше не имеет отношения к карте locations.

...