Java for Beginner
677 subscribers
546 photos
155 videos
12 files
837 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
WeakHashMap, особенности использования

WeakHashMap — это реализация интерфейса Map, которая использует слабые ссылки на ключи. Эта структура данных особенно полезна для кеширования, где не требуется жесткая ссылка на ключи, и объекты могут быть автоматически удалены сборщиком мусора, когда они больше не используются. Рассмотрим подробно особенности и использование WeakHashMap.

Основные особенности WeakHashMap

Слабые ссылки: Ключи в WeakHashMap хранятся как слабые ссылки. Это значит, что если на объект-ключ нет жестких ссылок из других объектов, то он может быть удален сборщиком мусора.
Автоматическое удаление: При удалении ключа сборщиком мусора, соответствующая пара ключ-значение также удаляется из карты.
Потокобезопасность:
WeakHashMap не является потокобезопасной и требует внешней синхронизации при доступе из нескольких потоков.

Внутреннее устройство WeakHashMap

WeakHashMap основан на массиве сегментов (bucket), где каждая ячейка массива может содержать связанный список элементов, как в HashMap. Однако, ключи хранятся в виде слабых ссылок (WeakReference), что позволяет сборщику мусора удалять их при необходимости.

Примеры использования WeakHashMap

Создание и добавление элементов
import java.util.WeakHashMap;
import java.util.Map;

public class WeakHashMapExample {
public static void main(String[] args) {
WeakHashMap<String, String> weakMap = new WeakHashMap<>();

String key1 = new String("key1");
String key2 = new String("key2");

weakMap.put(key1, "value1");
weakMap.put(key2, "value2");

System.out.println("Before GC: " + weakMap);

key1 = null;
System.gc();

// Подождем немного, чтобы GC мог удалить key1
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("After GC: " + weakMap);
}
}


Основные методы WeakHashMap

Метод put

Добавляет пару ключ-значение в карту.
WeakHashMap<String, Integer> map = new WeakHashMap<>();
map.put("Apple", 50);
map.put("Banana", 30);


Метод get

Возвращает значение, связанное с указанным ключом.
Integer value = map.get("Apple");
System.out.println("Value for key 'Apple': " + value);


Метод remove

Удаляет запись по ключу и возвращает удаленное значение.
Integer removedValue = map.remove("Banana");
System.out.println("Removed value: " + removedValue);


Метод containsKey


Проверяет, содержится ли ключ в карте.
boolean contains = map.containsKey("Apple");
System.out.println("Contains key 'Apple': " + contains);


Метод containsValue

Проверяет, содержится ли значение в карте.
boolean containsValue = map.containsValue(50);
System.out.println("Contains value 50: " + containsValue);


Метод size

Возвращает количество элементов в карте.
int size = map.size();
System.out.println("Size of the map: " + size);


Метод isEmpty

Проверяет, пуста ли карта.
boolean isEmpty = map.isEmpty();
System.out.println("Is the map empty: " + isEmpty);


Метод clear

Очищает карту, удаляя все элементы.
map.clear();
System.out.println("Size after clear: " + map.size());



Особенности использования WeakHashMap

Кеширование

WeakHashMap идеально подходит для кеширования данных, которые можно восстанавливать, если они удалены сборщиком мусора. Например, кеширование изображений в приложении, где изображения могут быть загружены повторно, если они были удалены.

Автоматическое удаление
В ситуациях, когда необходимо автоматически удалять элементы карты при отсутствии ссылок на ключи, WeakHashMap будет полезен. Например, для ассоциации метаданных с объектами без предотвращения их сборки мусора.


Полезные ссылки для более полного ознакомления с WeakHashMap (спасибо авторам за их кропотливую работу):
https://www.baeldung.com/java-weakhashmap
https://javarush.com/quests/lectures/questservlets.level18.lecture08

#Java #Training #Medium #WeakHashMap
Внутреннее устройство WeakHashMap

Основные компоненты

Бакеты:


WeakHashMap использует массив бакетов для хранения элементов. Каждый бакет представляет собой связанный список, который хранит элементы с одинаковым значением хэш-кода (коллизии).

Слабые ссылки (Weak References):

Ключи в WeakHashMap хранятся в виде слабых ссылок (java.lang.ref.WeakReference). Это означает, что ключи могут быть удалены сборщиком мусора, если на них больше нет жестких ссылок.

Структура записи (Entry):

Каждый элемент в WeakHashMap представлен экземпляром внутреннего класса WeakHashMap.Entry. Этот класс расширяет WeakReference<K> и содержит дополнительные поля для значения (V) и ссылки на следующий элемент в связанном списке (для коллизий).

Сборка мусора:

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


Механизм работы

Хэширование:

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

Добавление элементов:

Новый элемент добавляется в соответствующий бакет. Если бакет уже содержит элементы с одинаковым хэш-кодом, новый элемент добавляется в конец связанного списка.

Удаление элементов:

Когда ключ становится недоступным для приложения (не имеет жестких ссылок), сборщик мусора удаляет его запись из памяти. WeakHashMap автоматически удаляет такие записи при следующем доступе или модификации.

Примеры использования

Пример 1: Простой пример использования WeakHashMap
import java.util.WeakHashMap;

public class WeakHashMapExample {
public static void main(String[] args) {
WeakHashMap<String, String> map = new WeakHashMap<>();

String key1 = new String("key1");
String value1 = "value1";
map.put(key1, value1);

String key2 = new String("key2");
String value2 = "value2";
map.put(key2, value2);

System.out.println("Map before GC: " + map);

// Убираем жесткие ссылки на ключи
key1 = null;
key2 = null;

// Вызываем сборщик мусора
System.gc();

// Небольшая задержка для того, чтобы сборщик мусора успел сработать
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("Map after GC: " + map);
}
}


В этом примере мы создаем WeakHashMap и добавляем в нее две пары ключ-значение. Затем убираем жесткие ссылки на ключи и вызываем сборщик мусора. После сборки мусора элементы с ключами, на которые больше нет жестких ссылок, удаляются из карты.

Пример 2: Использование WeakHashMap для кеширования
WeakHashMap часто используется для кеширования данных, которые могут быть автоматически удалены, когда они больше не нужны. Это позволяет эффективно управлять памятью.
import java.util.WeakHashMap;

public class ImageCache {
private WeakHashMap<String, byte[]> cache = new WeakHashMap<>();

public byte[] getImage(String imageName) {
byte[] image = cache.get(imageName);
if (image == null) {
image = loadImageFromDisk(imageName);
cache.put(imageName, image);
}
return image;
}

private byte[] loadImageFromDisk(String imageName) {
// Заглушка для примера, возвращаем пустой массив
return new byte[0];
}

public static void main(String[] args) {
ImageCache imageCache = new ImageCache();
byte[] image1 = imageCache.getImage("image1.png");
byte[] image2 = imageCache.getImage("image2.png");

System.out.println("Image1 loaded: " + (image1 != null));
System.out.println("Image2 loaded: " + (image2 != null));
}
}

#Java #Training #Medium #WeakHashMap