Java for Beginner
777 subscribers
754 photos
220 videos
12 files
1.27K links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
LinkedList: последовательный доступ через цепочку узлов

Архитектурные основы связного списка
LinkedList реализует список на основе двусвязного списка, где каждый элемент хранится в отдельном узле, содержащем ссылки на данные, предыдущий и следующий узлы.

Эта архитектура fundamentally меняет механизм доступа к элементам:

Последовательный доступ вместо прямого
Линейная временная сложность доступа по индексу
Отсутствие преимуществ пространственной локальности
Дополнительные затраты на обход цепочки


Структура узла и организация данных
Каждый узел LinkedList содержит три ключевых компонента:
Node {
E item; // хранимый элемент
Node<E> next; // ссылка на следующий узел
Node<E> prev; // ссылка на предыдущий узел
}
Список поддерживает ссылки на первый (head) и последний (tail) узлы, а также счетчик размера.


Детальный процесс выполнения get(index)


Фаза валидации и стратегического выбора
Как и в ArrayList, первым шагом является проверка корректности индекса:

Проверка границ:
Убеждаются, что индекс находится в диапазоне [0, size-1].

Выбор стратегии обхода:
В зависимости от положения индекса выбирается оптимальная точка начала обхода:
Если индекс находится в первой половине списка (index < size / 2), обход начинается с головы (head)
Если индекс находится во второй половине, обход начинается с хвоста (tail)
Эта оптимизация уменьшает среднее количество шагов обхода с n/2 до n/4.


Фаза последовательного обхода
После выбора начальной точки начинается процесс пошагового перемещения по цепочке узлов:

Инициализация обхода:
Создается временная переменная-указатель, которая устанавливается на начальный узел (head или tail).

Последовательное перемещение:
Для каждого шага обхода:
Если движение от головы, указатель перемещается к следующему узлу (
node.next)
Если движение от хвоста, указатель перемещается к предыдущему узлу (node.prev)
Счетчик текущей позиции обновляется


Достижение целевой позиции:
Процесс продолжается до тех пор, пока текущая позиция не совпадет с запрошенным индексом.

Фаза извлечения и возврата результата
Когда целевой узел найден:

Извлечение элемента:
Из поля item целевого узла извлекается хранимый объект.

Возврат результата:
Объект возвращается вызывающему коду. Как и в ArrayList, если узел содержит null, возвращается null.


Производительность и характеристики доступа

Временная сложность
Операция get в LinkedList имеет временную сложность O(n) в худшем случае, где n — количество элементов в списке. Однако благодаря двунаправленному обходу средняя сложность составляет O(n/4) = O(n).

Зависимость от паттерна доступа
Худший случай:
Доступ к элементу в середине большого списка требует обхода примерно n/2 узлов.

Лучший случай:
Доступ к первому или последнему элементу требует всего одного шага.

Средний случай:
При равномерном распределении запросов среднее количество шагов составляет n/4.

Влияние на производительность

Отсутствие кэширования:
Из-за разрозненного расположения узлов в памяти отсутствуют преимущества кэширования процессора.

Overhead обхода:
Каждый шаг обхода требует разыменования ссылки и проверки условий, что создает дополнительную нагрузку.


#Java #для_новичков #beginner #List #ArrayList #LinkedList #get
👍1
Сравнительный анализ производительности

Количественные характеристики

Время доступа:
ArrayList: 5-10 наносекунд на операцию (не зависит от размера)
LinkedList: 10-50 наносекунд × количество пройденных узлов


Потребление памяти:
ArrayList: ~4 байта на элемент (в плотно заполненном массиве)
LinkedList: ~24-32 байта на элемент (затраты на узел)


Качественные различия

Пространственная локальность:
ArrayList: Отличная — элементы расположены непрерывно
LinkedList: Плохая — элементы разбросаны по куче


Масштабируемость:
ArrayList: Идеальная — постоянное время независимо от размера
LinkedList: Линейная деградация — время растет пропорционально размеру



Специализированные реализации List

CopyOnWriteArrayList


Механизм доступа:
Использует snapshot массив, что обеспечивает thread-safe доступ без блокировок:
Операция get просто обращается к текущему snapshot массива
Отсутствие блокировок и contention между читателями
Гарантированная consistency во время итерации


Производительность:
Сопоставима с ArrayList для операций чтения, но с дополнительным уровнем indirection.

Vector

Устаревший synchronized доступ:

Все операции, включая get, синхронизированы, что создает излишний overhead в single-threaded сценариях.


Многопоточные аспекты доступа

Потокобезопасность операций чтения

Несинхронизированные реализации:

ArrayList и LinkedList не гарантируют корректность при concurrent модификациях:
Возможность чтения устаревших данных
Риск исключений при структурных изменениях во время доступа
Отсутствие happens-before отношений


Thread-safe альтернативы:
CopyOnWriteArrayList: Идеален для read-heavy workloads
Collections.synchronizedList(): Добавляет синхронизацию к стандартным реализациям
Vector: Устаревшая синхронизированная реализация



Практические рекомендации

Критерии выбора реализации

Выбор ArrayList когда:
Преобладает случайный доступ по индексу
Частые операции получения элементов
Известен или может быть оценен конечный размер списка
Критически важна производительность операций чтени
Память является ограниченным ресурсом


Выбор LinkedList когда:
Преобладают операции вставки/удаления в начала/конца списка
Основной паттерн доступа — последовательная итерация
Размер списка сильно варьируется
Операции доступа по индексу редки или предсказуемы



Влияние современных аппаратных архитектур

Иерархия памяти и кэширование

ArrayList:
Отличное использование L1/L2/L3 кэшей
Эффективный prefetching
Минимальные cache misses


LinkedList:
Частые cache misses из-за random access к памяти
Неэффективное использование prefetcher'а
Высокий penalty при промахах кэша


Влияние на реальную производительность

Разрыв в производительности между ArrayList и LinkedList для операций get может достигать 50-100 раз для больших списков и случайного доступа, что делает правильный выбор реализации критически важным для производительности приложения.


#Java #для_новичков #beginner #List #ArrayList #LinkedList #get
👍1
Что выведет код?

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

public class Task281125 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);

List<Integer> subList = list.subList(1, 3);
list.add(4);

System.out.println(subList.get(0));
System.out.println(subList.get(1));
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
50%
2 3
10%
2 4
10%
3 4
30%
ConcurrentModificationException
Вопрос с собеседований

Что такое «слабая ссылка» в Java? 🤓


Ответ:

WeakReference
позволяет объекту быть удаленным GC, если на него нет сильных ссылок.

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

Это гибкий способ управления памятью без ручного освобождения.



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Развлечения Вам с утра.

Убедите нейросеть дать вам скидку!

Хоть она и матерится как сапожник я смог)) Поржал от души - пробуйте)
Я его сделал 😂😂😂
История IT-технологий сегодня — 29 ноября


ℹ️ Кто родился в этот день

Магдолна Зиманьи , урожденная Магдолна Дьёрдьи (Будапешт , 29 ноября 1934 — Будапешт, 27 марта 2016) — венгерская математик и информатик, одна из пионеров компьютерной науки в Венгрии, разработала методы и подходы в ранней информатике.


🌐 Знаковые события

1972 — Atari выпустила игру Pong, один из первых коммерчески успешных аркадных видеоигр, что стало важным шагом в развитии индустрии видеоигр. Выпуск Pong считается отправной точкой для массового распространения видеоигр и началом игровой индустрии, которая со временем выросла в крупную отрасль развлечений и технологий.


#Biography #Birth_Date #Events #29Ноября
Please open Telegram to view this post
VIEW IN TELEGRAM
С 22.11 по 28.11
Предыдущий пост(с 15.11 по 21.11)

Воскресный мотивационный пост:
Кем ты видишь себя в будущем в IT?

Запись встреч/видео:
не было

Обучающие статьи:

Java:
Коллекции в Java

Глава 2. List — списки в Java
Реализации: ArrayList и LinkedList. Сравнение производительности
Метод add
Метод get

GraphQL
Реализация GraphQL на сервере
GraphQL vs REST vs gRPC

Полезные статьи и видео:
Spring без боли: моя шпаргалка для собесов в Java
Можно ли спасти LinkedList? Пишем быстрый List на связном списке

Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
👍2
История IT-технологий сегодня — 30 ноября


ℹ️ Кто родился в этот день

Питер Ли (родился 30 ноября 1960 года) — американский учёный компьютерных наук, президент и глава Microsoft Research, ранее — руководитель отдела безопасности ПО в DARPA; известен трудами в области компиляторов и программных систем безопасности.

Войцех Заремба (родился 30 ноября 1988 года) — польско-американский компьютерный учёный, сооснователь OpenAI; руководил работами по робототехнике и нейросетям (в том числе Rubik’s Cube-робот) и затем над GPT/вопросами ИИ.


🌐 Знаковые события

1609 — Галилео Галилей составил первую карту лунной поверхности.

2022 — запуск ChatGPT.


#Biography #Birth_Date #Events #30Ноября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Технический разбор: Spring WebFlux Gateway с JWT аутентификацией

Архитектурный контекст:
Это API Gateway сервис, который проксирует запросы к downstream-сервисам

Паттерн: Gateway Aggregation с аутентификацией на уровне шлюза

Детальный разбор компонентов:

Spring Security Integration
@PreAuthorize("hasRole('USER')")

Method-level security с SpEL выражением


Автоматическая проверка ролей из JWT токена
Вызывается до выполнения метода контроллера



JWT Processing

@AuthenticationPrincipal Jwt jwt

Spring Security автоматически инжектирует парсированный JWT


JWT объект предоставляет доступ к claims: jwt.getSubject(), jwt.getClaims()
Токен уже провалидирован на уровне security filter chain



Header Management Strategy
.headers(h -> {
h.add("X-User-Id", jwt.getSubject()); // User ID для сквозной идентификации
h.add(HttpHeaders.AUTHORIZATION, authHeader); // Оригинальный токен для downstream-сервисов
})


X-User-Id - кастомный header для передачи идентификатора пользователя
Проброс оригинального Authorization header для цепочки аутентификации



Reactive WebClient Configuration

return taskWebClient.get()
.uri("/api/v1/tasks/{taskId}", taskId) // URI template с подстановкой
.retrieve() // Выполнение запроса
.bodyToMono(TaskDto.class) // Десериализация ответа


Non-blocking HTTP клиент на основе Reactor Netty
Type-safe десериализация в DTO
Автоматическая обработка connection pooling и retries



Error Handling Pipeline

.onErrorMap(WebClientResponseException.class, ex -> {
if (ex.getStatusCode().is4xxClientError()) {
return new AuthClientException(ex.getResponseBodyAsString(), ex.getStatusCode().value());
} else if (ex.getStatusCode().is5xxServerError()) {
return new AuthServerException(ex.getResponseBodyAsString(), ex.getStatusCode().value());
}
return ex;
})

Дифференциация ошибок по статус-кодам


Сохранение тела ответа из downstream-сервиса
Преобразование в domain-specific исключения



Flow выполнения:
HTTP Request → Spring Security Filter Chain
JWT Validation & Role Checking
Controller Method Invocation
WebClient Request to Downstream Service
Response Processing & Error Mapping
HTTP Response to Client



Преимущества данного подхода:

Централизованная аутентификация в gateway
Сквозная передача контекста пользователя
Реактивная non-blocking архитектура
Единая точка обработки ошибок
Type-safe коммуникация между сервисами



Требуемые конфигурации:
Spring Security с JWT decoder
Настроенный WebClient с connection pooling
Global exception handler для кастомных исключений
Мониторинг и логирование межсервисных вызовов


Данная реализация демонстрирует production-ready подход к построению API Gateway в микросервисной архитектуре с полным циклом аутентификации и обработки ошибок.
👍1🤯1
По прежнему набираю несколько человек на обучение Java.


Пишите, будет интересно🫡
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21
История IT-технологий сегодня — 01 декабря


ℹ️ Кто родился в этот день

Корнелиус Шумахер (нем. Cornelius Schumacher; род. 1 декабря 1969, Тюбинген, Германия) — немецкий разработчик свободного ПО, активист свободного софта, внёс вклад в KDE — популярную среду рабочего стола для GNU/Linux.


🌐 Знаковые события

1677— состоялся запуск первой в мире коммерческой системы интерактивного кабельного телевидения в Колумбусе (Огайо, США). Система предлагала порядка 30 каналов, из которых часть были обычными вещательными, часть — платными (pay-per-view), а часть — интерактивными, с возможностью «обратной связи» пользователя через пульт.


#Biography #Birth_Date #Events #01Декабря
Please open Telegram to view this post
VIEW IN TELEGRAM
Advanced GraphQL: реактивность и Federation

GraphQL уже давно не ограничивается статическими запросами к одной базе.

Современные системы требуют:
реактивности: live updates, push-события на фронтенд;
масштабируемости: объединение схем из разных сервисов;
микросервисной интеграции: разные источники данных и форматы;
единый клиентский интерфейс: фронт видит единую схему, хотя данные приходят из нескольких микросервисов.


Эти задачи решаются через Subscriptions, Federation, Schema Stitching, GraphQL Gateway.


1. Subscriptions и live updates

1.1 Что такое Subscription

Subscription — это тип операции GraphQL, который подписывается на события и получает данные по мере их появления, в отличие от Query/Mutation, где данные запрашиваются один раз.

Используется для:
чатов и уведомлений;
реального мониторинга (метрики, логи);
обновления UI при изменении данных на сервере.


1.2 Механика на сервере

Клиент подписывается на событие через WebSocket или Server-Sent Events (SSE).
Сервер регистрирует подписку и хранит её в памяти или через pub/sub (Redis, Kafka).
При событии вызываются соответствующие резолверы Subscription, результат отправляется клиенту.


1.3 Пример на Spring Boot с graphql-java

Схема (schema.graphqls)
type Subscription {
postAdded: Post!
}


Резолвер Subscription
@Component
public class PostSubscription implements GraphQLSubscriptionResolver {

private final Publisher<Post> postPublisher;

public PostSubscription(Publisher<Post> postPublisher) {
this.postPublisher = postPublisher;
}

public Publisher<Post> postAdded() {
return postPublisher;
}
}


Публикация события (например, после мутации)
@Component
public class PostMutation implements GraphQLMutationResolver {

private final Publisher<Post> postPublisher;
private final PostService postService;

public PostMutation(PostService postService, Publisher<Post> postPublisher) {
this.postService = postService;
this.postPublisher = postPublisher;
}

public Post createPost(CreatePostInput input) {
Post newPost = postService.create(input);
postPublisher.publish(newPost); // пушим в подписчиков
return newPost;
}
}

Таким образом фронтенд автоматически получает новые посты без повторных запросов.


1.4 Реактивная интеграция с gRPC

Микросервис может уведомлять GraphQL через gRPC стриминг (Server Streaming).
GraphQL Gateway принимает события и пушит их клиентам через Subscription.
Реализуется через Publisher или Flux (Project Reactor) в Java.


Пример с Project Reactor:
public Publisher<Post> postAdded() {
return Flux.from(postGrpcStub.subscribePosts());
}



#Java #middle #GraphQL
👍1
2. Federation / Schema stitching

2.1 Зачем нужна Federation

В микросервисной архитектуре каждая команда может иметь свой GraphQL-сервис.
Фронтенду нужен единый endpoint, а не десятки отдельных.

Schema stitching: объединяет схемы в один endpoint вручную.

Apollo Federation: более продвинутый стандарт, позволяющий каждому сервису быть федеративным узлом.

2.2 Принцип работы Federation

Subgraph Service — каждый сервис предоставляет свою часть схемы: User, Post, Comment.
Gateway / Apollo Gateway — объединяет схемы subgraph и решает, какой сервис вызывать для каждого запроса.
Reference resolver — позволяет связать типы из разных сервисов (например, User в Post).

Пример на Java (с Spring Boot + GraphQL Federation, библиотека graphql-java-federation):

Сервис Users
type User @key(fields: "id") {
id: ID!
name: String!
}


Сервис Posts
type Post {
id: ID!
title: String!
author: User @provides(fields: "name")
}



Java resolver для
Post.author
@Component
public class PostResolver implements GraphQLResolver<Post> {

private final UserGrpc.UserBlockingStub userStub;

public PostResolver(UserGrpc.UserBlockingStub userStub) {
this.userStub = userStub;
}

public User author(Post post) {
UserRequest req = UserRequest.newBuilder().setId(post.getAuthorId()).build();
UserResponse resp = userStub.getUser(req);
return mapToGraphQLUser(resp);
}
}

Gateway собирает всю федеративную схему и возвращает фронтенду единый API.



3. GraphQL Gateway и объединение данных

3.1 Роль Gateway

Аггрегирует данные из нескольких микросервисов (REST, gRPC, базы, Kafka).
Решает проблемы N+1 через batching (DataLoader).
Управляет кешированием и throttling.
Поддерживает Subscriptions и Federation.


3.2 Пример архитектуры
[Frontend SPA / Mobile] --GraphQL--> [GraphQL Gateway] --gRPC--> [UserService]
|--> [PostService]
|--> [CommentService]
|--> [External REST API]


Особенности:

Gateway использует DataLoader для агрегации запросов, уменьшения количества вызовов к сервисам.
Subscriptions могут получать события из gRPC стримов или Kafka и пушить клиенту.



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

4.1 Live feed

Мобильное приложение подписывается на postAdded.
PostService пушит новые посты через gRPC или внутренний EventBus.
Gateway трансформирует данные в GraphQL Subscription → клиент получает обновления моментально.


4.2 Микросервисная интеграция


UserService и PostService разрабатываются разными командами.
Gateway объединяет их схемы через Federation.
Фронтенд видит единый API: user(id: 1) { name posts { title } }, не зная, что posts приходит из другого сервиса.


4.3 Agreggation + caching

Gateway кеширует данные User на 5 минут.
PostService вызывается только для новых постов.
DataLoader агрегирует все запросы к UserService за одну операцию.



5. Лучшие практики

Использовать Federation для масштабируемых командных проектов.
Subscription через WebSocket + Publisher/Flux для реактивных интерфейсов.
DataLoader для оптимизации N+1 вызовов в распределённых сервисах.
Разделять ответственность: микросервисы предоставляют свои типы и резолверы, Gateway агрегирует.
Event-driven подход для live updates: gRPC streaming, Kafka, Redis Pub/Sub.
Мониторинг: трассировка на уровне каждого subgraph, latency, throughput.
Эволюция схем: добавление новых полей без ломки клиентов, депрекация старых.



#Java #middle #GraphQL
👍1
Что выведет код?

import java.util.Optional;

public class Task011225 {
public static void main(String[] args) {
Optional<String> emptyOpt = Optional.empty();
Optional<String> valueOpt = Optional.of("hello");
Optional<String> nullOpt = Optional.ofNullable(null);

System.out.println(valueOpt.get());
System.out.println(nullOpt.isPresent());
System.out.println(emptyOpt.isPresent());
System.out.println(emptyOpt.get());
}
}


#Tasks
Вопрос с собеседований

Для чего нужен метод join() в потоках? 🤓


Ответ:

join()
заставляет текущий поток ждать завершения другого потока.

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

Правильное использование предотвращает гонки данных и обеспечивает согласованность программы.



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1