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

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Что выведет код?

import java.util.ArrayList;
import java.util.List;

public class ListConcatenationChallenge {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();
list1.add("a");
list1.add("b");
list1.add("c");

List<String> list2 = new ArrayList<>();
list2.add("d");
list2.add("e");
list2.add("f");

String result = concatenateLists(list1, list2);
System.out.println(result);
}

public static String concatenateLists(List<String> list1, List<String> list2) {
StringBuilder sb = new StringBuilder();

for (int i = 0; i < list1.size(); i++) {
sb.append(list1.get(i));
sb.append(list2.get(i));
}

return sb.toString();
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
0%
"abcdef"
25%
"adbcef"
75%
"adbecf"
0%
"abcdfe"
Ну хоть что-то ищет😂

https://t.me/Java_for_beginner_dev

#Mems
Внутреннее устройство LinkedHashMap

1. Связанный список для порядка элементов

LinkedHashMap расширяет HashMap, добавляя поддержку связанного списка для поддержания порядка элементов. Каждый элемент хранится в виде узла двусвязного списка, что позволяет поддерживать порядок вставки или порядок доступа.
static class Entry<K, V> extends HashMap.Node<K, V> {
Entry<K, V> before, after;

Entry(int hash, K key, V value, HashMap.Node<K, V> next) {
super(hash, key, value, next);
}
}


2. Поля для управления порядком

LinkedHashMap добавляет два новых поля для управления порядком элементов:

transient LinkedHashMap.Entry<K, V> head;
transient LinkedHashMap.Entry<K, V> tail;

Эти поля указывают на первый и последний элементы в связанном списке.

3. Механизм управления порядком элементов

Для управления порядком элементов LinkedHashMap переопределяет методы newNode, afterNodeAccess и afterNodeInsertion:

newNode: Создает новый узел и добавляет его в конец связанного списка.
Node<K, V> newNode(int hash, K key, V value, Node<K, V> e) {
LinkedHashMap.Entry<K, V> p = new LinkedHashMap.Entry<>(hash, key, value, e);
linkNodeLast(p);
return p;
}

private void linkNodeLast(LinkedHashMap.Entry<K, V> p) {
LinkedHashMap.Entry<K, V> last = tail;
tail = p;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
}


afterNodeAccess: Обновляет порядок элементов при доступе, если карта настроена на порядок доступа.
void afterNodeAccess(Node<K, V> e) {
LinkedHashMap.Entry<K, V> last;
if (accessOrder && (last = tail) != e) {
LinkedHashMap.Entry<K, V> p = (LinkedHashMap.Entry<K, V>) e, b = p.before, a = p.after;
p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a != null)
a.before = b;
else
last = b;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
tail = p;
++modCount;
}
}


afterNodeInsertion: Удаляет самый старый элемент, если карта настроена на удаление старейших элементов.
void afterNodeInsertion(boolean evict) {
LinkedHashMap.Entry<K, V> first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;
removeNode(hash(key), key, null, false, true);
}
}


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


1. Конструкторы

LinkedHashMap предоставляет несколько конструкторов для создания карты с различными настройками:

public LinkedHashMap() {
super();
}

public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
}

public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}

public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}


2. Метод put
Метод put добавляет пару ключ-значение в карту. Если ключ уже существует, его значение обновляется.
public V put(K key, V value) {
return super.put(key, value);
}


3. Метод get

Метод get возвращает значение, связанное с указанным ключом. Если ключ не найден, возвращается null. При этом порядок элементов обновляется, если карта настроена на порядок доступа.

public V get(Object key) {
Node<K, V> e;
if ((e = getNode(hash(key), key)) == null)
return null;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}


4. Метод remove
Метод remove удаляет пару ключ-значение по указанному ключу и возвращает удаленное значение.
public V remove(Object key) {
Node<K, V> e;
return (e = removeNode(hash(key), key, null, false, true)) == null ? null : e.value;
}


5. Метод containsKey


Метод containsKey проверяет, содержит ли карта указанный ключ.
public boolean containsKey(Object key) {
return getNode(hash(key), key) != null;
}


#Java #Training #Medium #LinkedHashMap
6. Метод containsValue

Метод containsValue проверяет, содержит ли карта указанное значение.

public boolean containsValue(Object value) {
for (Node<K, V> e = head; e != null; e = e.after) {
if (value.equals(e.value))
return true;
}
return false;
}


7. Метод clear


Метод clear очищает карту, удаляя все элементы.
public void clear() {
super.clear();
head = tail = null;
}


8. Метод entrySet

Метод entrySet возвращает набор всех пар ключ-значение в карте.
public Set<Map.Entry<K, V>> entrySet() {
return new LinkedEntrySet();
}


#Java #Training #Medium #LinkedHashMap
"Если мы в ответе за тех кого приручили, в ответе ли мы за то, что они спроектировали?"🧐

#Mems
Введение в TreeMap, принципы работы и внутреннее устройство

TreeMap — это реализация интерфейса NavigableMap, основанная на красно-черном дереве. Он предоставляет отсортированное отображение ключей и является мощным инструментом для хранения отсортированных данных.

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

Отсортированное отображение:
Ключи в TreeMap всегда отсортированы в порядке возрастания, если не указан другой компаратор.
Красно-черное дерево: Использует самобалансирующееся бинарное дерево для хранения элементов.
Эффективность: Операции вставки, удаления и поиска выполняются за O(log n).


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


Красно-черное дерево — это тип самобалансирующегося бинарного дерева поиска с следующими свойствами:

Каждый узел либо красный, либо черный.
Корень дерева всегда черный.
Все листья (NULL-указатели) считаются черными.
Красный узел не может иметь красных дочерних узлов (т.е., красные узлы не могут быть рядом).
Любой путь от корня до листа содержит одинаковое количество черных узлов.


Класс Entry

Внутренний класс Entry представляет узел в дереве:

static final class Entry<K, V> implements Map.Entry<K, V> {
K key;
V value;
Entry<K, V> left, right, parent;
boolean color = BLACK;

Entry(K key, V value, Entry<K, V> parent) {
this.key = key;
this.value = value;
this.parent = parent;
}

public K getKey() { return key; }
public V getValue() { return value; }
public V setValue(V value) {
V oldValue = this.value;
this.value = value;
return oldValue;
}
}


Принципы работы TreeMap

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

Удаление
Удаление элемента включает три основных шага:
Найти узел для удаления.
Удалить узел.
Балансировать дерево, если это необходимо.


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


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


Метод put
Метод put добавляет пару ключ-значение в TreeMap:
public V put(K key, V value) {
Entry<K, V> t = root;
if (t == null) {
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K, V> parent;
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0) t = t.left;
else if (cmp > 0) t = t.right;
else return t.setValue(value);
} while (t != null);
} else {
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0) t = t.left;
else if (cmp > 0) t = t.right;
else return t.setValue(value);
} while (t != null);
}
Entry<K, V> e = new Entry<>(key, value, parent);
if (cmp < 0) parent.left = e;
else parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}


Метод get

Метод get возвращает значение по ключу:
public V get(Object key) {
Entry<K, V> p = getEntry(key);
return (p == null ? null : p.value);
}

final Entry<K, V> getEntry(Object key) {
if (comparator != null) return getEntryUsingComparator(key);
Comparable<? super K> k = (Comparable<? super K>) key;
Entry<K, V> p = root;
while (p != null) {
int cmp = k.compareTo(p.key);
if (cmp < 0) p = p.left;
else if (cmp > 0) p = p.right;
else return p;
}
return null;
}


Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://javarush.com/groups/posts/2584-osobennosti-treemap
https://www.baeldung.com/java-treemap

#Java #Training #Medium #TreeMap
Что выведет код?

public class ComplexVariableAssignmentChallenge {
public static void main(String[] args) {
int intVar1 = 8;
int intVar2 = 3;
double doubleVar1 = 4.5;
double doubleVar2 = 2.5;
String strVar1 = "Sum: ";
String strVar2 = "Product: ";

String resultSum = strVar1 + (intVar1 + doubleVar1) + ", " + (intVar2 + doubleVar2);
String resultProduct = strVar2 + (intVar1 * doubleVar1) + ", " + (intVar2 * doubleVar2);
System.out.println(resultSum);
System.out.println(resultProduct);
}
}

#Tasks
Суровая правда жизни🤌

https://t.me/Java_for_beginner_dev

#Mems
Основные методы TreeMap и их применение

Конструкторы TreeMap

Без параметров
TreeMap<String, Integer> map = new TreeMap<>();


С компаратором

TreeMap<String, Integer> map = new TreeMap<>(Comparator.reverseOrder());


Из другого Map
Map<String, Integer> anotherMap = new HashMap<>();
TreeMap<String, Integer> map = new TreeMap<>(anotherMap);


Из SortedMap
SortedMap<String, Integer> sortedMap = new TreeMap<>(anotherMap);
TreeMap<String, Integer> map = new TreeMap<>(sortedMap);


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

Метод put

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


Метод 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("Orange");
System.out.println("Contains key 'Orange': " + contains);


Метод containsValue

Проверяет, содержится ли значение в карте.
boolean containsValue = map.containsValue(20);
System.out.println("Contains value 20: " + 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());


Специфические методы TreeMap

Метод firstKey

Возвращает первый (минимальный) ключ.
String firstKey = map.firstKey();
System.out.println("First key: " + firstKey);


Метод lastKey

Возвращает последний (максимальный) ключ.
String lastKey = map.lastKey();
System.out.println("Last key: " + lastKey);


Метод pollFirstEntry

Удаляет и возвращает первый (минимальный) элемент.
Map.Entry<String, Integer> firstEntry = map.pollFirstEntry();
System.out.println("Polled first entry: " + firstEntry);


Метод pollLastEntry


Удаляет и возвращает последний (максимальный) элемент.
Map.Entry<String, Integer> lastEntry = map.pollLastEntry();
System.out.println("Polled last entry: " + lastEntry);



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

Пример 1: Печать элементов в порядке возрастания ключей
TreeMap<String, Integer> map = new TreeMap<>();
map.put("Apple", 50);
map.put("Banana", 30);
map.put("Orange", 20);

for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}


Пример 2: Использование метода subMap

Возвращает отображение части карты.
map.put("Grapes", 40);
SortedMap<String, Integer> subMap = map.subMap("Apple", "Orange");
for (Map.Entry<String, Integer> entry : subMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}


Пример 3: Получение диапазона ключей
NavigableMap<String, Integer> tailMap = map.tailMap("Banana", true);
for (Map.Entry<String, Integer> entry : tailMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}

#Java #Training #Medium #TreeMap
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
Что выведет код?

import java.util.*;

public class AlgorithmChallenge {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(5, 2, 8, 7, 1);
Collections.sort(numbers, (a, b) -> b - a);

int sum = 0;
for (int i = 0; i < numbers.size(); i++) {
if (i % 2 == 0) {
sum += numbers.get(i) * 2;
} else {
sum -= numbers.get(i) * 3;
}
}
System.out.println("Result: " + sum);
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
0%
3
14%
5
29%
14
57%
1
Таких не берут в Junior'ы😁

https://t.me/Java_for_beginner_dev

#Mems
Внутреннее устройство 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
Всем доброго солнечного субботнего утра! ☀️

За окном +30 градусов, а это значит надо отдыхать!

Делитесь, как Вы проводите эти выходные?
Напоминаю!☝️

Завтра в 16:00 по МСК, мы вновь собираемся на онлайн-кодинг!

Писать будем игру Пинг-Понг изучая библиотеки Swing и Awt!

А вы придете?🧐
На рабочий стол. Однозначно😏

https://t.me/Java_for_beginner_dev

#Mems
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

Всем хорошего настроения! 👻