ConcurrentHashMap.newKeySet
Jasne, rozbijmy ten kod kawałek po kawałku:
private final Set<String> excludedPackages = ConcurrentHashMap.newKeySet(8);
ConcurrentHashMap.newKeySet(8):
-
ConcurrentHashMap: To klasa z pakietujava.util.concurrent. Jest to implementacja mapy, która jest bezpieczna wątkowo (thread-safe) i zoptymalizowana pod kątem wysokiej współbieżności (wielu wątków operujących na niej jednocześnie). Zazwyczaj oferuje lepszą wydajność w środowiskach wielowątkowych niż np.Collections.synchronizedMap(new HashMap<>()). -
.newKeySet(): To statyczna metoda fabryczna klasyConcurrentHashMap. Zwraca onaSet, który jest w rzeczywistości "widokiem" na klucze obiektuConcurrentHashMap. Kiedy dodajesz element do tegoSetu, tak naprawdę dodajesz klucz do wewnętrznejConcurrentHashMap(z jakąś stałą, nieistotną wartością, np.Boolean.TRUE). Jest to efektywny sposób na uzyskanie bezpiecznego wątkowoSetu.
Masz rację, ConcurrentHashMap.newKeySet() zwraca instancję klasy KeySetView.
To bardzo sprytny sposób na uzyskanie bezpiecznego wątkowo Setu bez potrzeby pisania zupełnie nowej implementacji od zera.
Oto dlaczego jest to tak inicjowane i jak to działa:
-
Problem: Potrzeba bezpiecznego wątkowo
SetuStandardowe implementacjeSetw Javie, takie jakHashSetczyTreeSet, nie są bezpieczne wątkowo. Jeśli wiele wątków próbuje jednocześnie modyfikować taki zbiór, może to prowadzić do niespójnego stanu i błędów (np.ConcurrentModificationExceptionlub utraty danych). Można by użyćCollections.synchronizedSet(new HashSet<>()), ale to rozwiązanie synchronizuje dostęp do całego zbioru za pomocą jednego globalnego zamka (locka), co może stać się wąskim gardłem wydajności przy dużej liczbie wątków. -
Rozwiązanie: Wykorzystanie istniejącej, wydajnej struktury
ConcurrentHashMapjest już wysoce zoptymalizowaną, bezpieczną wątkowo implementacją mapy. Zamiast pisać od podstaw nową, bezpieczną wątkowo implementacjęSetu, twórcy Javy postanowili wykorzystać istniejącą infrastrukturęConcurrentHashMap. -
Jak działa
KeySetView?
- "Widok" na klucze mapy:
KeySetViewto nie jest oddzielna kolekcja danych. Jest to specjalny "widok" (view) na klucze bazowego obiektuConcurrentHashMap. Oznacza to, że operacje naKeySetViewsą w rzeczywistości delegowane do operacji na tym wewnętrznymConcurrentHashMap. - Jak
Setjest symulowany przezMap? Klucze w mapie są z definicji unikalne – dokładnie tak, jak elementy wSet. Kiedy dodajesz element doSetuutworzonego przeznewKeySet(), tak naprawdę dzieje się coś takiego:
// Gdy robisz:
// myKeySet.add("jakiśKlucz");
// Wewnętrznie (koncepcyjnie) dzieje się:
// bazowyConcurrentHashMap.put("jakiśKlucz", JAKAŚ_STAŁA_WARTOŚĆ);
Ta JAKAŚ_STAŁA_WARTOŚĆ to zazwyczaj predefiniowany, statyczny obiekt, np. Boolean.TRUE. Nie jest on istotny z punktu widzenia użytkownika Setu – liczy się tylko obecność klucza.