Внутреннее устройство WeakHashMap
Основные компоненты
Бакеты:
WeakHashMap использует массив бакетов для хранения элементов. Каждый бакет представляет собой связанный список, который хранит элементы с одинаковым значением хэш-кода (коллизии).
Слабые ссылки (Weak References):
Ключи в WeakHashMap хранятся в виде слабых ссылок (java.lang.ref.WeakReference). Это означает, что ключи могут быть удалены сборщиком мусора, если на них больше нет жестких ссылок.
Структура записи (Entry):
Каждый элемент в WeakHashMap представлен экземпляром внутреннего класса WeakHashMap.Entry. Этот класс расширяет WeakReference<K> и содержит дополнительные поля для значения (V) и ссылки на следующий элемент в связанном списке (для коллизий).
Сборка мусора:
Сборщик мусора удаляет записи, ключи которых больше не используются. После удаления элемента его запись в бакете становится недействительной и удаляется при следующем доступе или изменении карты.
Механизм работы
Хэширование:
При добавлении элемента в карту ключ хэшируется, и результат используется для определения бакета, в который будет помещен элемент.
Добавление элементов:
Новый элемент добавляется в соответствующий бакет. Если бакет уже содержит элементы с одинаковым хэш-кодом, новый элемент добавляется в конец связанного списка.
Удаление элементов:
Когда ключ становится недоступным для приложения (не имеет жестких ссылок), сборщик мусора удаляет его запись из памяти. WeakHashMap автоматически удаляет такие записи при следующем доступе или модификации.
Примеры использования
Пример 1: Простой пример использования WeakHashMap
В этом примере мы создаем WeakHashMap и добавляем в нее две пары ключ-значение. Затем убираем жесткие ссылки на ключи и вызываем сборщик мусора. После сборки мусора элементы с ключами, на которые больше нет жестких ссылок, удаляются из карты.
Пример 2: Использование WeakHashMap для кеширования
WeakHashMap часто используется для кеширования данных, которые могут быть автоматически удалены, когда они больше не нужны. Это позволяет эффективно управлять памятью.
#Java #Training #Medium #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
This media is not supported in your browser
VIEW IN TELEGRAM
Запись нашей сегодняшней встречи -
https://youtu.be/PqW7agFgVts
Огромная благодарность @MrAbhorrent, @vovs03, @Alexander_Gors за участие и подсказки!
Сегодня мы создали консольную игру пинг-понг, в которую можно без проблем поиграть)))
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб канал!
Гит репозиторий с результатом - https://github.com/Oleborn/Ping_Pong_Project
Всем хорошего настроения! 👻
https://youtu.be/PqW7agFgVts
Огромная благодарность @MrAbhorrent, @vovs03, @Alexander_Gors за участие и подсказки!
Сегодня мы создали консольную игру пинг-понг, в которую можно без проблем поиграть)))
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб канал!
Гит репозиторий с результатом - https://github.com/Oleborn/Ping_Pong_Project
Всем хорошего настроения! 👻
IdentityHashMap, отличия от других Map
IdentityHashMap — это специальная реализация интерфейса Map в Java, которая использует оператор == для сравнения ключей и значений вместо метода equals(), который используется в большинстве других реализаций Map. Это означает, что в IdentityHashMap ключи считаются одинаковыми, если они ссылаются на один и тот же объект в памяти, а не если они логически равны.
Отличия от других реализаций Map
Сравнение ключей и значений:
HashMap, TreeMap и другие реализации Map используют метод equals() для сравнения ключей и значений.
IdentityHashMap использует оператор ==, что означает сравнение по ссылке, а не по содержимому.
Производительность:
IdentityHashMap может быть быстрее для некоторых операций, так как оператор == работает быстрее, чем метод equals().
В то же время, IdentityHashMap не гарантирует порядок элементов и не предназначен для использования в случаях, когда важно логическое равенство объектов.
Применение:
IdentityHashMap используется в специализированных случаях, таких как кеширование объектов с уникальными ссылками, когда требуется учитывать именно ссылки, а не содержимое объектов.
Другие реализации, такие как HashMap, подходят для большинства стандартных задач, где важно логическое равенство объектов.
Пример использования
В этом примере видно, что IdentityHashMap хранит два разных элемента для двух разных объектов key1 и key2, даже если их содержимое идентично. В то время как HashMap считает эти объекты одинаковыми из-за использования метода equals() и перезаписывает значение.
Полезные ссылки для более полного ознакомления с IdentityHashMap (спасибо авторам за их кропотливую работу):
https://www.baeldung.com/java-identityhashmap
#Java #Training #Medium #IdentityHashMap
IdentityHashMap — это специальная реализация интерфейса Map в Java, которая использует оператор == для сравнения ключей и значений вместо метода equals(), который используется в большинстве других реализаций Map. Это означает, что в IdentityHashMap ключи считаются одинаковыми, если они ссылаются на один и тот же объект в памяти, а не если они логически равны.
Отличия от других реализаций Map
Сравнение ключей и значений:
HashMap, TreeMap и другие реализации Map используют метод equals() для сравнения ключей и значений.
IdentityHashMap использует оператор ==, что означает сравнение по ссылке, а не по содержимому.
Производительность:
IdentityHashMap может быть быстрее для некоторых операций, так как оператор == работает быстрее, чем метод equals().
В то же время, IdentityHashMap не гарантирует порядок элементов и не предназначен для использования в случаях, когда важно логическое равенство объектов.
Применение:
IdentityHashMap используется в специализированных случаях, таких как кеширование объектов с уникальными ссылками, когда требуется учитывать именно ссылки, а не содержимое объектов.
Другие реализации, такие как HashMap, подходят для большинства стандартных задач, где важно логическое равенство объектов.
Пример использования
import java.util.IdentityHashMap;
import java.util.Map;
public class IdentityHashMapExample {
public static void main(String[] args) {
Map<String, String> identityMap = new IdentityHashMap<>();
String key1 = new String("key");
String key2 = new String("key");
identityMap.put(key1, "Value 1");
identityMap.put(key2, "Value 2");
System.out.println("Size of IdentityHashMap: " + identityMap.size()); // Output: 2
System.out.println("Value for key1: " + identityMap.get(key1)); // Output: Value 1
System.out.println("Value for key2: " + identityMap.get(key2)); // Output: Value 2
// Compare with HashMap
Map<String, String> hashMap = new HashMap<>();
hashMap.put(key1, "Value 1");
hashMap.put(key2, "Value 2");
System.out.println("Size of HashMap: " + hashMap.size()); // Output: 1
}
}
В этом примере видно, что IdentityHashMap хранит два разных элемента для двух разных объектов key1 и key2, даже если их содержимое идентично. В то время как HashMap считает эти объекты одинаковыми из-за использования метода equals() и перезаписывает значение.
Полезные ссылки для более полного ознакомления с IdentityHashMap (спасибо авторам за их кропотливую работу):
https://www.baeldung.com/java-identityhashmap
#Java #Training #Medium #IdentityHashMap
Baeldung
Java IdentityHashMap Class and Its Use Cases | Baeldung
Learn how to use IdentityHashMap in Java
Что выведет код?
#Tasks
import java.util.ArrayList;
import java.util.Collections;
public class ArrayListChallenge {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
Collections.addAll(numbers, 3, 1, 4, 1, 5, 9, 2, 6, 5);
int result = 0;
for (int i = 0; i < numbers.size(); i++) {
if (i % 2 == 0) {
result += numbers.get(i);
} else {
result -= numbers.get(i);
}
}
System.out.println("Result: " + result);
}
}
#Tasks
Основные методы IdentityHashMap и примеры использования
IdentityHashMap предоставляет основные методы интерфейса Map, такие как добавление, удаление и получение элементов.
Основные методы
put(K key, V value): Добавляет пару ключ-значение в карту.
get(Object key): Возвращает значение, связанное с указанным ключом.
remove(Object key): Удаляет элемент по указанному ключу.
size(): Возвращает количество элементов в карте.
containsKey(Object key): Проверяет, содержит ли карта указанный ключ.
containsValue(Object value): Проверяет, содержит ли карта указанное значение.
keySet(): Возвращает набор всех ключей в карте.
values(): Возвращает коллекцию всех значений в карте.
entrySet(): Возвращает набор всех пар ключ-значение в карте.
Примеры использования
В этом примере демонстрируются основные методы IdentityHashMap, такие как добавление, получение и удаление элементов, а также проверка наличия ключей и значений. Эти методы работают аналогично другим реализациям Map, за исключением того, что IdentityHashMap использует сравнение по ссылке.
#Java #Training #Medium #IdentityHashMap
IdentityHashMap предоставляет основные методы интерфейса Map, такие как добавление, удаление и получение элементов.
Основные методы
put(K key, V value): Добавляет пару ключ-значение в карту.
get(Object key): Возвращает значение, связанное с указанным ключом.
remove(Object key): Удаляет элемент по указанному ключу.
size(): Возвращает количество элементов в карте.
containsKey(Object key): Проверяет, содержит ли карта указанный ключ.
containsValue(Object value): Проверяет, содержит ли карта указанное значение.
keySet(): Возвращает набор всех ключей в карте.
values(): Возвращает коллекцию всех значений в карте.
entrySet(): Возвращает набор всех пар ключ-значение в карте.
Примеры использования
import java.util.IdentityHashMap;
import java.util.Map;
public class IdentityHashMapMethodsExample {
public static void main(String[] args) {
Map<String, String> identityMap = new IdentityHashMap<>();
String key1 = new String("key");
String key2 = new String("key");
// Метод put
identityMap.put(key1, "Value 1");
identityMap.put(key2, "Value 2");
// Метод get
System.out.println("Value for key1: " + identityMap.get(key1)); // Output: Value 1
System.out.println("Value for key2: " + identityMap.get(key2)); // Output: Value 2
// Метод size
System.out.println("Size of IdentityHashMap: " + identityMap.size()); // Output: 2
// Метод containsKey
System.out.println("Contains key1: " + identityMap.containsKey(key1)); // Output: true
System.out.println("Contains new key: " + identityMap.containsKey(new String("key"))); // Output: false
// Метод containsValue
System.out.println("Contains Value 1: " + identityMap.containsValue("Value 1")); // Output: true
// Метод remove
identityMap.remove(key1);
System.out.println("Size after removing key1: " + identityMap.size()); // Output: 1
// Методы keySet, values, entrySet
System.out.println("Keys: " + identityMap.keySet()); // Output: [key2]
System.out.println("Values: " + identityMap.values()); // Output: [Value 2]
System.out.println("Entries: " + identityMap.entrySet()); // Output: [key2=Value 2]
}
}
В этом примере демонстрируются основные методы IdentityHashMap, такие как добавление, получение и удаление элементов, а также проверка наличия ключей и значений. Эти методы работают аналогично другим реализациям Map, за исключением того, что IdentityHashMap использует сравнение по ссылке.
#Java #Training #Medium #IdentityHashMap
EnumMap, преимущества и особенности
EnumMap — это специализированная реализация интерфейса Map, предназначенная для использования с перечислениями (enum) в качестве ключей. Она отличается высокой производительностью и эффективностью использования памяти по сравнению с другими реализациями Map.
Основные характеристики EnumMap
Ключи — только перечисления:
Ключами в EnumMap могут быть только перечисления (enum). Это означает, что EnumMap предназначена исключительно для использования с типами enum.
Эффективное использование памяти:
EnumMap реализована как массив, что позволяет ей быть более компактной и эффективной по сравнению с другими реализациями Map.
Высокая производительность:
Операции вставки, поиска и удаления имеют постоянное время выполнения (O(1)), что делает EnumMap очень быстрой.
Порядок ключей:
EnumMap хранит ключи в порядке их естественного порядка, определенного в перечислении.
Примеры использования EnumMap
Определение перечисления
Создание EnumMap
С использованием пустого конструктора:
С использованием другой карты:
Основные методы EnumMap
Метод put:
Метод get:
Метод remove:
Метод containsKey:
Метод size:
Метод clear:
Преимущества использования EnumMap
Производительность:
EnumMap реализована на основе массива, что делает доступ к элементам очень быстрым. Операции вставки, удаления и поиска имеют время выполнения O(1).
Эффективность использования памяти:
Поскольку EnumMap использует массив для хранения значений, она значительно экономит память по сравнению с другими реализациями Map, такими как HashMap.
Безопасность типов:
EnumMap использует перечисления в качестве ключей, что гарантирует безопасность типов и предотвращает ошибки, связанные с использованием неверных ключей.
Упорядоченность:
Ключи в EnumMap всегда упорядочены в порядке их определения в перечислении, что упрощает их использование и предсказуемость.
Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://www.baeldung.com/java-enum-map
https://medium.com/@javatechie/java-enummap-e78c7cf0acbf
#Java #Training #Medium #EnumMap
EnumMap — это специализированная реализация интерфейса Map, предназначенная для использования с перечислениями (enum) в качестве ключей. Она отличается высокой производительностью и эффективностью использования памяти по сравнению с другими реализациями Map.
Основные характеристики EnumMap
Ключи — только перечисления:
Ключами в EnumMap могут быть только перечисления (enum). Это означает, что EnumMap предназначена исключительно для использования с типами enum.
Эффективное использование памяти:
EnumMap реализована как массив, что позволяет ей быть более компактной и эффективной по сравнению с другими реализациями Map.
Высокая производительность:
Операции вставки, поиска и удаления имеют постоянное время выполнения (O(1)), что делает EnumMap очень быстрой.
Порядок ключей:
EnumMap хранит ключи в порядке их естественного порядка, определенного в перечислении.
Примеры использования EnumMap
Определение перечисления
enum Color {
RED, GREEN, BLUE;
}
Создание EnumMap
С использованием пустого конструктора:
EnumMap<Color, String> colorMap = new EnumMap<>(Color.class);
С использованием другой карты:
Map<Color, String> anotherMap = new HashMap<>();
anotherMap.put(Color.RED, "Red Color");
anotherMap.put(Color.GREEN, "Green Color");
EnumMap<Color, String> colorMap = new EnumMap<>(anotherMap);
Основные методы EnumMap
Метод put:
colorMap.put(Color.RED, "Red Color");
colorMap.put(Color.GREEN, "Green Color");
System.out.println(colorMap); // {RED=Red Color, GREEN=Green Color}
Метод get:
String color = colorMap.get(Color.RED);
System.out.println("Color for RED: " + color); // Color for RED: Red Color
Метод remove:
String removedColor = colorMap.remove(Color.GREEN);
System.out.println("Removed color: " + removedColor); // Removed color: Green Color
System.out.println(colorMap); // {RED=Red Color}
Метод containsKey:
boolean containsRed = colorMap.containsKey(Color.RED);
System.out.println("Contains RED: " + containsRed); // Contains RED: true
Метод size:
int size = colorMap.size();
System.out.println("Size of the map: " + size); // Size of the map: 1
Метод clear:
colorMap.clear();
System.out.println("Size after clear: " + colorMap.size()); // Size after clear: 0
Преимущества использования EnumMap
Производительность:
EnumMap реализована на основе массива, что делает доступ к элементам очень быстрым. Операции вставки, удаления и поиска имеют время выполнения O(1).
Эффективность использования памяти:
Поскольку EnumMap использует массив для хранения значений, она значительно экономит память по сравнению с другими реализациями Map, такими как HashMap.
Безопасность типов:
EnumMap использует перечисления в качестве ключей, что гарантирует безопасность типов и предотвращает ошибки, связанные с использованием неверных ключей.
Упорядоченность:
Ключи в EnumMap всегда упорядочены в порядке их определения в перечислении, что упрощает их использование и предсказуемость.
Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://www.baeldung.com/java-enum-map
https://medium.com/@javatechie/java-enummap-e78c7cf0acbf
#Java #Training #Medium #EnumMap
Baeldung
A Guide to EnumMap | Baeldung
Learn why if you aren't yet using EnumMap, you should be.
Что выведет код?
#Tasks
public class VariableChallenge {
public static void main(String[] args) {
long a = 123456789012345L;
boolean b = true;
double c = 1.2345;
double result = (b ? a * c : a / c) + (b && a > 1000000000 ? c : a);
System.out.println("Result: " + result);
}
}
#Tasks
Варианты ответа:
Anonymous Quiz
11%
152409725272920.1
5%
152409725568920.0
74%
1.5240740603574116E14
11%
123456789012345.0Е
Внутренняя структура EnumMap
EnumMap состоит из двух основных массивов: один для ключей и один для значений.
Массив ключей (keyUniverse):
Это массив всех возможных значений перечисления в том порядке, в котором они объявлены. Он создается один раз и используется для быстрого поиска индексов ключей.
keyUniverse инициализируется следующим образом:
Здесь keyType — это класс перечисления, переданный в конструктор EnumMap.
Массив значений (values):
Это массив значений, который соответствует ключам. Индекс значения в этом массиве соответствует индексу ключа в массиве keyUniverse.
Инициализация массива values:
Изначально все элементы массива values равны null.
Примеры использования EnumMap
Пример 1: Карта настроек цветов
Пример 2: Использование EnumMap в качестве счетчика
#Java #Training #Medium #EnumMap
EnumMap состоит из двух основных массивов: один для ключей и один для значений.
Массив ключей (keyUniverse):
Это массив всех возможных значений перечисления в том порядке, в котором они объявлены. Он создается один раз и используется для быстрого поиска индексов ключей.
private final Enum<?>[] keyUniverse;
keyUniverse инициализируется следующим образом:
keyUniverse = keyType.getEnumConstants();
Здесь keyType — это класс перечисления, переданный в конструктор EnumMap.
Массив значений (values):
Это массив значений, который соответствует ключам. Индекс значения в этом массиве соответствует индексу ключа в массиве keyUniverse.
private transient Object[] values;
Инициализация массива values:
values = new Object[keyUniverse.length];
Изначально все элементы массива values равны null.
Примеры использования EnumMap
Пример 1: Карта настроек цветов
enum Color {
RED, GREEN, BLUE;
}
public class EnumMapExample {
public static void main(String[] args) {
EnumMap<Color, String> colorMap = new EnumMap<>(Color.class);
colorMap.put(Color.RED, "Red Color");
colorMap.put(Color.GREEN, "Green Color");
colorMap.put(Color.BLUE, "Blue Color");
for (Color color : colorMap.keySet()) {
System.out.println(color + ": " + colorMap.get(color));
}
}
}
Пример 2: Использование EnumMap в качестве счетчика
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}
public class EnumMapCounter {
public static void main(String[] args) {
EnumMap<Day, Integer> dayCount = new EnumMap<>(Day.class);
// Инициализация счетчика для каждого дня недели
for (Day day : Day.values()) {
dayCount.put(day, 0);
}
// Увеличиваем счетчики для некоторых дней
dayCount.put(Day.MONDAY, dayCount.get(Day.MONDAY) + 1);
dayCount.put(Day.FRIDAY, dayCount.get(Day.FRIDAY) + 2);
dayCount.put(Day.SUNDAY, dayCount.get(Day.SUNDAY) + 3);
// Выводим результаты
for (Day day : dayCount.keySet()) {
System.out.println(day + ": " + dayCount.get(day));
}
}
}
#Java #Training #Medium #EnumMap
ArrayList: особенности и внутреннее устройство
ArrayList — это динамический массив, который является одной из наиболее часто используемых реализаций интерфейса List в Java. Он предоставляет упорядоченную коллекцию элементов и позволяет доступ к ним по индексу. В этом посте мы рассмотрим особенности и внутреннее устройство ArrayList.
Основные особенности ArrayList
Динамический размер:
В отличие от обычного массива, размер ArrayList может динамически изменяться. При добавлении элементов его емкость увеличивается автоматически.
Доступ по индексу:
ArrayList обеспечивает быстрый доступ к элементам по индексу. Операция получения элемента по индексу выполняется за постоянное время O(1).
Упорядоченность:
Элементы в ArrayList хранятся в том порядке, в котором они были добавлены.
Не синхронизированность:
ArrayList не является потокобезопасной коллекцией. Если необходимо использовать его в многопоточной среде, требуется внешняя синхронизация.
Внутреннее устройство ArrayList
ArrayList реализован как обертка над массивом, который динамически изменяет свой размер по мере добавления или удаления элементов. Рассмотрим основные аспекты внутреннего устройства ArrayList.
Массив для хранения элементов:
Внутри ArrayList используется массив Object[], называемый elementData, для хранения элементов.
Размер и емкость:
ArrayList имеет два важных параметра: size и capacity. size — это количество элементов, фактически находящихся в списке, а capacity — это размер внутреннего массива elementData.
Инициализация:
При создании ArrayList можно задать начальную емкость. Если она не указана, используется значение по умолчанию (обычно 10).
Если начальная емкость не указана:
Добавление элементов:
Метод add добавляет элемент в конец списка. При добавлении элемента проверяется, хватает ли текущей емкости массива. Если нет, создается новый массив с увеличенной емкостью, и элементы копируются в него.
Получение элементов:
Метод get возвращает элемент по указанному индексу. Операция выполняется за постоянное время O(1).
Удаление элементов:
Метод remove удаляет элемент по индексу или по значению. После удаления элемента все последующие элементы сдвигаются влево, чтобы заполнить пробел.
#Java #Training #Medium #ArrayList
ArrayList — это динамический массив, который является одной из наиболее часто используемых реализаций интерфейса List в Java. Он предоставляет упорядоченную коллекцию элементов и позволяет доступ к ним по индексу. В этом посте мы рассмотрим особенности и внутреннее устройство ArrayList.
Основные особенности ArrayList
Динамический размер:
В отличие от обычного массива, размер ArrayList может динамически изменяться. При добавлении элементов его емкость увеличивается автоматически.
Доступ по индексу:
ArrayList обеспечивает быстрый доступ к элементам по индексу. Операция получения элемента по индексу выполняется за постоянное время O(1).
Упорядоченность:
Элементы в ArrayList хранятся в том порядке, в котором они были добавлены.
Не синхронизированность:
ArrayList не является потокобезопасной коллекцией. Если необходимо использовать его в многопоточной среде, требуется внешняя синхронизация.
Внутреннее устройство ArrayList
ArrayList реализован как обертка над массивом, который динамически изменяет свой размер по мере добавления или удаления элементов. Рассмотрим основные аспекты внутреннего устройства ArrayList.
Массив для хранения элементов:
Внутри ArrayList используется массив Object[], называемый elementData, для хранения элементов.
private transient Object[] elementData;
Размер и емкость:
ArrayList имеет два важных параметра: size и capacity. size — это количество элементов, фактически находящихся в списке, а capacity — это размер внутреннего массива elementData.
Инициализация:
При создании ArrayList можно задать начальную емкость. Если она не указана, используется значение по умолчанию (обычно 10).
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = {};
} else {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
}
Если начальная емкость не указана:
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
Добавление элементов:
Метод add добавляет элемент в конец списка. При добавлении элемента проверяется, хватает ли текущей емкости массива. Если нет, создается новый массив с увеличенной емкостью, и элементы копируются в него.
public boolean add(E e) {
ensureCapacityInternal(size + 1); // проверка емкости
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // увеличивается на 50%
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
Получение элементов:
Метод get возвращает элемент по указанному индексу. Операция выполняется за постоянное время O(1).
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
Удаление элементов:
Метод remove удаляет элемент по индексу или по значению. После удаления элемента все последующие элементы сдвигаются влево, чтобы заполнить пробел.
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index + 1, elementData, index, numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
#Java #Training #Medium #ArrayList
Что выведет код?
#Tasks
import java.util.HashMap;
public class HashMapChallenge {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
map.put("D", 4);
map.put("E", 5);
int result = 0;
for (String key : map.keySet()) {
if (key.compareTo("C") < 0) {
result += map.get(key);
} else {
result -= map.get(key);
}
}
System.out.println("Result: " + result);
}
}
#Tasks
Основные компоненты ArrayList
Массив для хранения элементов:
Внутри ArrayList используется массив Object[] для хранения элементов. Этот массив называется elementData.
Размер и емкость:
ArrayList имеет два важных параметра: size и capacity. size — это текущее количество элементов в списке, а capacity — это размер внутреннего массива elementData.
Инициализация:
ArrayList можно создать с заданной начальной емкостью или без неё. Если емкость не указана, используется значение по умолчанию (обычно 10).
Пример использования ArrayList
#Java #Training #Medium #ArrayList
Массив для хранения элементов:
Внутри ArrayList используется массив Object[] для хранения элементов. Этот массив называется elementData.
private transient Object[] elementData;
Размер и емкость:
ArrayList имеет два важных параметра: size и capacity. size — это текущее количество элементов в списке, а capacity — это размер внутреннего массива elementData.
private int size;
Инициализация:
ArrayList можно создать с заданной начальной емкостью или без неё. Если емкость не указана, используется значение по умолчанию (обычно 10).
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = {};
} else {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
}
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
Пример использования ArrayList
import java.util.ArrayList;
public class ArrayListExample {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
// Добавление элементов
list.add("Apple");
list.add("Banana");
list.add("Cherry");
// Получение элементов
System.out.println("First element: " + list.get(0)); // Apple
// Удаление элемента
list.remove("Banana");
System.out.println("List after removal: " + list); // [Apple, Cherry]
// Размер списка
System.out.println("Size of list: " + list.size()); // 2
}
}
#Java #Training #Medium #ArrayList
LinkedList, отличие от ArrayList
LinkedList — это одна из реализаций интерфейса List в Java. Он представляет собой двусвязный список, где каждый элемент содержит ссылки на предыдущий и следующий элементы. LinkedList подходит для сценариев, где часто выполняются операции вставки и удаления элементов в середине списка.
Особенности LinkedList
Двусвязный список:
Каждый элемент в LinkedList содержит ссылки на предыдущий и следующий элементы, что позволяет эффективно добавлять и удалять элементы в середине списка.
Доступ к элементам:
В отличие от ArrayList, доступ к элементам в LinkedList осуществляется линейным поиском, что делает его менее эффективным для операций случайного доступа.
Итерация по элементам:
Поскольку элементы связаны ссылками, итерация по списку может быть выполнена с постоянным использованием памяти и временем для операций добавления и удаления.
Не синхронизированность:
Как и ArrayList, LinkedList не является потокобезопасной коллекцией. В многопоточных средах требуется внешняя синхронизация.
Отличие от ArrayList
Структура хранения:
ArrayList использует массив для хранения элементов, тогда как LinkedList использует двусвязный список.
Время доступа:
ArrayList обеспечивает быстрый доступ к элементам по индексу (O(1)), в то время как LinkedList требует линейного времени (O(n)) для доступа к элементам по индексу.
Вставка и удаление элементов:
Вставка и удаление элементов в середине списка эффективнее в LinkedList (O(1)), в то время как в ArrayList эти операции требуют сдвига элементов и выполняются за время O(n).
Емкость и размер:
В ArrayList размер массива увеличивается автоматически при добавлении элементов, что может привести к перераспределению памяти. LinkedList не имеет проблемы перераспределения памяти, так как элементы связаны ссылками.
Примеры использования
Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://habr.com/ru/articles/127864/
https://javarush.com/groups/posts/1938-linkedlist
#Java #Training #Medium #LinkedList
LinkedList — это одна из реализаций интерфейса List в Java. Он представляет собой двусвязный список, где каждый элемент содержит ссылки на предыдущий и следующий элементы. LinkedList подходит для сценариев, где часто выполняются операции вставки и удаления элементов в середине списка.
Особенности LinkedList
Двусвязный список:
Каждый элемент в LinkedList содержит ссылки на предыдущий и следующий элементы, что позволяет эффективно добавлять и удалять элементы в середине списка.
Доступ к элементам:
В отличие от ArrayList, доступ к элементам в LinkedList осуществляется линейным поиском, что делает его менее эффективным для операций случайного доступа.
Итерация по элементам:
Поскольку элементы связаны ссылками, итерация по списку может быть выполнена с постоянным использованием памяти и временем для операций добавления и удаления.
Не синхронизированность:
Как и ArrayList, LinkedList не является потокобезопасной коллекцией. В многопоточных средах требуется внешняя синхронизация.
Отличие от ArrayList
Структура хранения:
ArrayList использует массив для хранения элементов, тогда как LinkedList использует двусвязный список.
Время доступа:
ArrayList обеспечивает быстрый доступ к элементам по индексу (O(1)), в то время как LinkedList требует линейного времени (O(n)) для доступа к элементам по индексу.
Вставка и удаление элементов:
Вставка и удаление элементов в середине списка эффективнее в LinkedList (O(1)), в то время как в ArrayList эти операции требуют сдвига элементов и выполняются за время O(n).
Емкость и размер:
В ArrayList размер массива увеличивается автоматически при добавлении элементов, что может привести к перераспределению памяти. LinkedList не имеет проблемы перераспределения памяти, так как элементы связаны ссылками.
Примеры использования
import java.util.LinkedList;
import java.util.List;
public class LinkedListExample {
public static void main(String[] args) {
List<String> linkedList = new LinkedList<>();
// Добавление элементов
linkedList.add("Apple");
linkedList.add("Banana");
linkedList.add("Cherry");
// Получение элемента
System.out.println("First element: " + linkedList.get(0)); // Apple
// Вставка элемента
linkedList.add(1, "Orange");
System.out.println("After insertion: " + linkedList); // [Apple, Orange, Banana, Cherry]
// Удаление элемента
linkedList.remove("Banana");
System.out.println("After removal: " + linkedList); // [Apple, Orange, Cherry]
// Итерация по элементам
for (String fruit : linkedList) {
System.out.println(fruit);
}
}
}
Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://habr.com/ru/articles/127864/
https://javarush.com/groups/posts/1938-linkedlist
#Java #Training #Medium #LinkedList
Хабр
Структуры данных в картинках. LinkedList
Приветствую вас, хабражители! Продолжаю начатое, а именно, пытаюсь рассказать (с применением визуальных образов) о том как реализованы некоторые структуры данных в Java. В прошлый раз мы говорили об...
Что выведет код?
#Tasks
import java.util.LinkedList;
public class LinkedListChallenge {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
list.add(5);
list.add(15);
list.add(25);
list.add(35);
list.add(45);
int sum = 0;
for (int i = 1; i < list.size(); i += 2) {
sum += list.get(i);
}
list.add(1, sum);
list.removeLast();
list.addFirst(sum);
int result = 1;
for (int value : list) {
result *= value;
}
System.out.println("Result: " + result);
}
}
#Tasks