Telegram Group & Telegram Channel
💥 Задача: Почему эта структура «ломается» в многопоточной среде?


import java.util.*;

public class BrokenImmutable {
private final Map<String, List<String>> data;

public BrokenImmutable(Map<String, List<String>> input) {
this.data = Collections.unmodifiableMap(input);
}

public Map<String, List<String>> getData() {
return data;
}

public static void main(String[] args) {
Map<String, List<String>> base = new HashMap<>();
base.put("key", new ArrayList<>(List.of("a")));

BrokenImmutable bi = new BrokenImmutable(base);
Map<String, List<String>> d = bi.getData();

d.get("key").add("🚨");

System.out.println(bi.getData());
}
}


🔍 Разбор:
С первого взгляда кажется, что BrokenImmutable — иммутабельный класс. Мы оборачиваем Map через Collections.unmodifiableMap, и поле data — final.

Но проблема в глубине структуры.

unmodifiableMap запрещает перезапись ключей, но не делает элементы внутри truly immutable. В данном случае, значение по ключу "key" — это ArrayList, которую легко модифицировать.

💣 В main() мы получили доступ к внутреннему списку и… тихо сломали инвариант класса, добавив "🚨".

Решение:
Чтобы сделать структуру действительно иммутабельной, нужно:

Копировать и оборачивать значения внутри Map.

Сделать глубокую защиту:


public BrokenImmutable(Map<String, List<String>> input) {
Map<String, List<String>> copy = new HashMap<>();
for (Map.Entry<String, List<String>> e : input.entrySet()) {
copy.put(e.getKey(), List.copyOf(e.getValue())); // immutable list
}
this.data = Map.copyOf(copy); // immutable map
}



Теперь никто не сможет мутировать data, даже если получит на него ссылку.

🧠 Вопрос на подумать:
А что если вместо ArrayList внутри Map был бы CopyOnWriteArrayList или ImmutableList от Guava? Почему CopyOnWriteArrayList — тоже плохой выбор для truly immutable структур?

@javatg



tg-me.com/javatg/1869
Create:
Last Update:

💥 Задача: Почему эта структура «ломается» в многопоточной среде?


import java.util.*;

public class BrokenImmutable {
private final Map<String, List<String>> data;

public BrokenImmutable(Map<String, List<String>> input) {
this.data = Collections.unmodifiableMap(input);
}

public Map<String, List<String>> getData() {
return data;
}

public static void main(String[] args) {
Map<String, List<String>> base = new HashMap<>();
base.put("key", new ArrayList<>(List.of("a")));

BrokenImmutable bi = new BrokenImmutable(base);
Map<String, List<String>> d = bi.getData();

d.get("key").add("🚨");

System.out.println(bi.getData());
}
}


🔍 Разбор:
С первого взгляда кажется, что BrokenImmutable — иммутабельный класс. Мы оборачиваем Map через Collections.unmodifiableMap, и поле data — final.

Но проблема в глубине структуры.

unmodifiableMap запрещает перезапись ключей, но не делает элементы внутри truly immutable. В данном случае, значение по ключу "key" — это ArrayList, которую легко модифицировать.

💣 В main() мы получили доступ к внутреннему списку и… тихо сломали инвариант класса, добавив "🚨".

Решение:
Чтобы сделать структуру действительно иммутабельной, нужно:

Копировать и оборачивать значения внутри Map.

Сделать глубокую защиту:


public BrokenImmutable(Map<String, List<String>> input) {
Map<String, List<String>> copy = new HashMap<>();
for (Map.Entry<String, List<String>> e : input.entrySet()) {
copy.put(e.getKey(), List.copyOf(e.getValue())); // immutable list
}
this.data = Map.copyOf(copy); // immutable map
}



Теперь никто не сможет мутировать data, даже если получит на него ссылку.

🧠 Вопрос на подумать:
А что если вместо ArrayList внутри Map был бы CopyOnWriteArrayList или ImmutableList от Guava? Почему CopyOnWriteArrayList — тоже плохой выбор для truly immutable структур?

@javatg

BY Java


Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283

Share with your friend now:
tg-me.com/javatg/1869

View MORE
Open in Telegram


Java Telegram | DID YOU KNOW?

Date: |

The global forecast for the Asian markets is murky following recent volatility, with crude oil prices providing support in what has been an otherwise tough month. The European markets were down and the U.S. bourses were mixed and flat and the Asian markets figure to split the difference.The TSE finished modestly lower on Friday following losses from the financial shares and property stocks.For the day, the index sank 15.09 points or 0.49 percent to finish at 3,061.35 after trading between 3,057.84 and 3,089.78. Volume was 1.39 billion shares worth 1.30 billion Singapore dollars. There were 285 decliners and 184 gainers.

Java from cn


Telegram Java
FROM USA