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
PriorityQueue, принципы работы и внутреннее устройство

PriorityQueue — это класс из пакета java.util, который реализует интерфейс Queue. В отличие от обычной очереди (FIFO), PriorityQueue основана на приоритетах элементов. Приоритет определяется с помощью естественного порядка элементов или через предоставленный компаратор.

import java.util.PriorityQueue;

public class PriorityQueueExample {
public static void main(String[] args) {
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();

priorityQueue.add(4);
priorityQueue.add(1);
priorityQueue.add(3);

while (!priorityQueue.isEmpty()) {
System.out.println(priorityQueue.poll());
}
}
}


В этом примере PriorityQueue автоматически упорядочивает элементы, так что при удалении элементов они извлекаются в порядке возрастания: 1, 3, 4.


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


Естественный порядок или компаратор: Элементы могут упорядочиваться на основе их естественного порядка (если элементы реализуют интерфейс Comparable) или на основе компаратора, предоставленного при создании очереди.
Бинарная куча (Binary Heap): Внутренняя реализация PriorityQueue основана на бинарной куче, которая является частично упорядоченным двоичным деревом. Это позволяет эффективно добавлять элементы и извлекать минимальный элемент.
Время выполнения операций: Основные операции PriorityQueue (вставка, удаление минимального элемента) выполняются за логарифмическое время O(log n), где n — количество элементов в очереди.


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

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

public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable {
private static final int DEFAULT_INITIAL_CAPACITY = 11;
private Object[] queue;
private int size;
private final Comparator<? super E> comparator;

public PriorityQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}

public PriorityQueue(int initialCapacity) {
this(initialCapacity, null);
}

public PriorityQueue(int initialCapacity, Comparator<? super E> comparator) {
if (initialCapacity < 1)
throw new IllegalArgumentException();
this.queue = new Object[initialCapacity];
this.comparator = comparator;
}

// Основные методы: add, poll, offer, remove, etc.
}


Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://www.baeldung.com/java-priorityqueue
https://sky.pro/media/ispolzovanie-priorityqueue-v-java/

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

import java.util.PriorityQueue;

public class PriorityQueueChallenge {
public static void main(String[] args) {
PriorityQueue<String> pq = new PriorityQueue<>();
pq.add("apple");
pq.add("banana");
pq.add("cherry");
pq.add("date");
pq.add("elderberry");

StringBuilder result = new StringBuilder();

while (!pq.isEmpty()) {
String value = pq.poll();
if (value.length() % 2 == 0) {
pq.add(value.substring(1));
} else {
result.append(value.charAt(0));
}
}

System.out.println("Result: " + result);
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
50%
abce
50%
abcde
0%
aaahl
0%
aacde
У него не было шансов👻

https://t.me/Java_for_beginner_dev

#Mems
Завтра в 17:00 по МСК, приглашаем всех на онлайн решение задач с Сodewars!

Решать задачи для Вас и вместе с Вами, будет @Alexander_Gors , за что ему сердечное спасибо! 🤝

Приходите и прокачивайте свои знания!

Ждем всех!
Основные методы PriorityQueue и примеры использования

add(E e):
Добавляет элемент в очередь. Если элемент null, выбрасывает NullPointerException.
PriorityQueue<Integer> pq = new PriorityQueue<>();
pq.add(10);
pq.add(20);
pq.add(15);


offer(E e):
Добавляет элемент в очередь. Возвращает true, если элемент был успешно добавлен, и false в противном случае.
pq.offer(5);


poll():
Возвращает и удаляет элемент с наивысшим приоритетом (минимальный элемент). Возвращает null, если очередь пуста.
Integer top = pq.poll(); // Возвращает 5 и удаляет его из очереди


peek():
Возвращает элемент с наивысшим приоритетом, но не удаляет его. Возвращает null, если очередь пуста.
Integer top = pq.peek(); // Возвращает 10, но не удаляет его


remove(Object o):
Удаляет указанный элемент из очереди, если он присутствует. Возвращает true, если элемент был успешно удален, и false в противном случае.
boolean removed = pq.remove(15); // Удаляет элемент 15


contains(Object o):
Проверяет, присутствует ли указанный элемент в очереди. Возвращает true, если элемент найден, и false в противном случае.
boolean contains = pq.contains(20); // Проверяет наличие элемента 20


size():
Возвращает количество элементов в очереди.
int size = pq.size(); // Возвращает количество элементов в очереди


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

Реализация задачи с приоритетом:
import java.util.PriorityQueue;
import java.util.Comparator;

class Task {
private String name;
private int priority;

public Task(String name, int priority) {
this.name = name;
this.priority = priority;
}

public int getPriority() {
return priority;
}

@Override
public String toString() {
return name + ": " + priority;
}
}

class TaskComparator implements Comparator<Task> {
public int compare(Task t1, Task t2) {
return Integer.compare(t1.getPriority(), t2.getPriority());
}
}

public class TaskScheduler {
public static void main(String[] args) {
PriorityQueue<Task> taskQueue = new PriorityQueue<>(new TaskComparator());

taskQueue.add(new Task("Task 1", 2));
taskQueue.add(new Task("Task 2", 1));
taskQueue.add(new Task("Task 3", 3));

while (!taskQueue.isEmpty()) {
System.out.println(taskQueue.poll());
}
}
}


Использование с Comparator для обратного порядка:
PriorityQueue<Integer> reversePQ = new PriorityQueue<>(Comparator.reverseOrder());

reversePQ.add(10);
reversePQ.add(20);
reversePQ.add(15);

while (!reversePQ.isEmpty()) {
System.out.println(reversePQ.poll());
}


Модель с приоритетом задач на основе времени выполнения:
import java.util.PriorityQueue;

class Job implements Comparable<Job> {
private String jobName;
private int executionTime;

public Job(String jobName, int executionTime) {
this.jobName = jobName;
this.executionTime = executionTime;
}

@Override
public int compareTo(Job other) {
return Integer.compare(this.executionTime, other.executionTime);
}

@Override
public String toString() {
return jobName + ": " + executionTime;
}
}

public class JobScheduler {
public static void main(String[] args) {
PriorityQueue<Job> jobQueue = new PriorityQueue<>();

jobQueue.add(new Job("Job 1", 30));
jobQueue.add(new Job("Job 2", 10));
jobQueue.add(new Job("Job 3", 20));

while (!jobQueue.isEmpty()) {
System.out.println(jobQueue.poll());
}
}
}


#Java #Training #Medium #PriorityQueue
ArrayDeque, внутреннее устройство, особенности и преимущества

ArrayDeque — это реализация двусторонней очереди (deque) на основе массивов, предоставляемая в пакете java.util. Она представляет собой гибкую структуру данных, которая поддерживает вставку и удаление элементов с обеих сторон с амортизированным постоянным временем.

import java.util.ArrayDeque;

public class ArrayDequeExample {
public static void main(String[] args) {
ArrayDeque<Integer> deque = new ArrayDeque<>();

deque.addFirst(1);
deque.addLast(2);
deque.addFirst(3);
deque.addLast(4);

while (!deque.isEmpty()) {
System.out.println(deque.pollFirst());
}
}
}


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



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

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

public class ArrayDeque<E> extends AbstractCollection<E> implements Deque<E>, Cloneable, Serializable {
private transient E[] elements;
private transient int head;
private transient int tail;

public ArrayDeque() {
elements = (E[]) new Object[16];
}

public ArrayDeque(int initialCapacity) {
elements = (E[]) new Object[initialCapacity];
}

// Основные методы: addFirst, addLast, pollFirst, pollLast, etc.
}


Особенности и преимущества

Циклический массив: Использование циклического массива позволяет избежать необходимости перемещения элементов при вставке и удалении с обеих сторон.
Амортизированное постоянное время: Вставка и удаление элементов с обеих сторон выполняются в амортизированное постоянное время O(1), за исключением случаев расширения массива.
Отсутствие блокировок: ArrayDeque не синхронизирована, что делает её быстрее по сравнению с синхронизированными структурами данных, такими как LinkedBlockingDeque.
Гибкость: Поддержка операций вставки и удаления с обеих сторон очереди предоставляет большую гибкость в использовании.


Преимущества использования ArrayDeque

Производительность: ArrayDeque обеспечивает более высокую производительность по сравнению с LinkedList для операций вставки и удаления элементов с обеих сторон.
Гибкость: Она поддерживает как стековые (push, pop), так и очередные (offer, poll) операции, что делает её универсальной для различных задач.
Эффективное использование памяти: Благодаря циклическому массиву ArrayDeque эффективно использует память, минимизируя количество операций по перемещению элементов.


import java.util.ArrayDeque;

public class ArrayDequeExample {
public static void main(String[] args) {
ArrayDeque<Integer> deque = new ArrayDeque<>();

// Добавление элементов
deque.addFirst(1);
deque.addLast(2);
deque.addFirst(3);
deque.addLast(4);

// Извлечение элементов
System.out.println(deque.pollFirst()); // 3
System.out.println(deque.pollLast()); // 4
System.out.println(deque.pollFirst()); // 1
System.out.println(deque.pollLast()); // 2
}
}

В этом примере демонстрируются основные операции вставки и извлечения элементов с обеих сторон очереди.

Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://www.baeldung.com/java-array-deque
https://metanit.com/java/tutorial/5.7.php

#Java #Training #Medium #ArrayDeque
Варианты ответа:
Anonymous Quiz
17%
45
17%
10
33%
25
33%
175
Что выведет код?

import java.util.ArrayDeque;

public class ArrayDequeChallenge {
public static void main(String[] args) {
ArrayDeque<Integer> deque = new ArrayDeque<>();
for (int i = 0; i < 10; i++) {
deque.add(i);
}

while (deque.size() > 1) {
deque.removeFirst();
if (deque.size() > 1) {
deque.addLast(deque.removeFirst() + deque.removeLast());
}
}

System.out.println("Result: " + deque.peek());
}
}


#Tasks
Мы научим Вас плохому😂

https://t.me/Java_for_beginner_dev

#Mems
Внимание!

На гитхабе (возможно, где-то еще) стали появляться поддельные версии goodbyedpi.exe с вирусом.
Тот архив с паролем, имейте ввиду. Поддельный goodbyedpi.exe значительно большего веса (в 40+ раз). Оригинальный ~100 КБ, поддельный > 4 МБ.
Благодаря сообществу
ntc.party удалено уже 4 репозитория на гитхабе с поддельным goodbyedpi.exe,
но почти наверняка эти подделки распространились в интернете.


#От_подписчиков
Встреча создана! ☝️

Заходите порешать задачки вместе с нами!⭐️

Ждем всех!
https://telemost.yandex.ru/j/42492956505565
Live stream started
Основные методы ArrayDeque и их применение

Основные методы ArrayDeque:

addFirst(E e):
Добавляет элемент в начало очереди. Если очередь заполнена, увеличивает её размер.
ArrayDeque<Integer> deque = new ArrayDeque<>();
deque.addFirst(10);
deque.addFirst(20);
System.out.println(deque); // [20, 10]


addLast(E e):
Добавляет элемент в конец очереди. Если очередь заполнена, увеличивает её размер.
deque.addLast(30);
System.out.println(deque); // [20, 10, 30]


offerFirst(E e):
Предлагает добавить элемент в начало очереди. Возвращает true, если элемент был добавлен успешно.
deque.offerFirst(40);
System.out.println(deque); // [40, 20, 10, 30]


offerLast(E e):
Предлагает добавить элемент в конец очереди. Возвращает true, если элемент был добавлен успешно.
deque.offerLast(50);
System.out.println(deque); // [40, 20, 10, 30, 50]


pollFirst():
Возвращает и удаляет первый элемент из очереди. Возвращает null, если очередь пуста.
Integer first = deque.pollFirst();
System.out.println(first); // 40
System.out.println(deque); // [20, 10, 30, 50]


pollLast():
Возвращает и удаляет последний элемент из очереди. Возвращает null, если очередь пуста.
Integer last = deque.pollLast();
System.out.println(last); // 50
System.out.println(deque); // [20, 10, 30]


peekFirst():
Возвращает первый элемент из очереди, не удаляя его. Возвращает null, если очередь пуста.
Integer peekFirst = deque.peekFirst();
System.out.println(peekFirst); // 20


peekLast():
Возвращает последний элемент из очереди, не удаляя его. Возвращает null, если очередь пуста.
Integer peekLast = deque.peekLast();
System.out.println(peekLast); // 30


push(E e):
Вставляет элемент на вершину стека. Эквивалентен методу addFirst(E e).
deque.push(60);
System.out.println(deque); // [60, 20, 10, 30]


pop():
Возвращает и удаляет элемент с вершины стека. Эквивалентен методу pollFirst().
Integer pop = deque.pop();
System.out.println(pop); // 60
System.out.println(deque); // [20, 10, 30]



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


Реализация стека с использованием ArrayDeque:
import java.util.ArrayDeque;

public class StackExample {
public static void main(String[] args) {
ArrayDeque<Integer> stack = new ArrayDeque<>();

stack.push(1);
stack.push(2);
stack.push(3);

while (!stack.isEmpty()) {
System.out.println(stack.pop());
}
}
}


Реализация очереди с использованием ArrayDeque:
import java.util.ArrayDeque;

public class QueueExample {
public static void main(String[] args) {
ArrayDeque<Integer> queue = new ArrayDeque<>();

queue.addLast(1);
queue.addLast(2);
queue.addLast(3);

while (!queue.isEmpty()) {
System.out.println(queue.pollFirst());
}
}
}


Реализация двусторонней очереди с использованием ArrayDeque:
import java.util.ArrayDeque;

public class DequeExample {
public static void main(String[] args) {
ArrayDeque<Integer> deque = new ArrayDeque<>();

deque.addFirst(1);
deque.addLast(2);
deque.addFirst(3);
deque.addLast(4);

while (!deque.isEmpty()) {
System.out.println(deque.pollFirst());
}
}
}


#Java #Training #Medium #ArrayDeque
Java for Beginner pinned «Вчера мы провели трансляцию в канале по решению задач с Codewar. Устраивает ли вас такой формат, нужно ли делать запись, для пересмотра?»
LinkedBlockingQueue, отличия от других очередей.

LinkedBlockingQueue — это реализация блокирующей очереди на основе связанного списка, предоставляемая в пакете java.util.concurrent. Она поддерживает опциональную ограниченную емкость и используется для передачи данных между потоками с возможностью блокировки.

Основные отличия от других очередей:

Блокирующая очередь: Ожидает свободного места для добавления или доступного элемента для извлечения.
Основана на связанном списке: В отличие от ArrayBlockingQueue, которая использует массив, LinkedBlockingQueue использует связанный список.
Опциональная ограниченная емкость: Вы можете задать максимальную емкость очереди. По умолчанию емкость не ограничена.


import java.util.concurrent.LinkedBlockingQueue;

public class LinkedBlockingQueueExample {
public static void main(String[] args) {
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);

try {
queue.put(1);
queue.put(2);
System.out.println(queue.take());
System.out.println(queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


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

LinkedBlockingQueue реализует блокирующую очередь с использованием двух внутренних объектов Node, а также использует механизмы блокировок для управления доступом к очереди.

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

Внутренний класс Node:
Узел, содержащий данные и ссылку на следующий элемент в очереди.
static class Node<E> {
E item;
Node<E> next;

Node(E x) { item = x; }
}


Голова и хвост очереди:

head: Ссылка на первый узел в очереди.
last: Ссылка на последний узел в очереди.

private transient Node<E> head;
private transient Node<E> last;


Механизмы блокировки:


Две раздельные блокировки для вставки и удаления: putLock и takeLock.

private final ReentrantLock putLock = new ReentrantLock();
private final Condition notFull = putLock.newCondition();
private final ReentrantLock takeLock = new ReentrantLock();
private final Condition notEmpty = takeLock.newCondition();


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

Вставка элемента (put):
Захватывается блокировка putLock.
Проверяется, не превышает ли очередь максимальную емкость.
Создается новый узел и добавляется в конец очереди.
Если очередь была пустой, сигнализируется о наличии новых элементов (notEmpty.signal()).
Освобождается блокировка putLock.


Извлечение элемента (take):
Захватывается блокировка takeLock.
Проверяется, не пустая ли очередь.
Удаляется узел из начала очереди.
Если очередь была заполнена, сигнализируется о наличии свободного места (notFull.signal()).
Освобождается блокировка takeLock.


import java.util.concurrent.LinkedBlockingQueue;

public class LinkedBlockingQueueExample {
public static void main(String[] args) {
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(2);

// Вставка элементов
new Thread(() -> {
try {
queue.put(1);
System.out.println("Inserted 1");
queue.put(2);
System.out.println("Inserted 2");
queue.put(3);
System.out.println("Inserted 3");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();

// Извлечение элементов
new Thread(() -> {
try {
Thread.sleep(2000);
System.out.println("Removed " + queue.take());
System.out.println("Removed " + queue.take());
System.out.println("Removed " + queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}


Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://www.geeksforgeeks.org/linkedblockingqueue-class-in-java/
https://www.baeldung.com/java-queue-linkedblocking-concurrentlinked

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

import java.util.concurrent.LinkedBlockingQueue;

public class LinkedBlockingQueueChallenge {
public static void main(String[] args) throws InterruptedException {
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
for (int i = 0; i < 10; i++) {
queue.put(i);
}

int result = 0;
while (!queue.isEmpty()) {
result += queue.take();
if (!queue.isEmpty()) {
queue.put(queue.take() * 2);
}
}

System.out.println("Result: " + result);
}
}


#Tasks
Варинаты ответа:
Anonymous Quiz
40%
115
30%
129
30%
126
0%
131