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

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Метод keySet()

Метод keySet() возвращает представление ключей Map в виде Set. Это представление фокусируется исключительно на ключах, предоставляя упрощенный view данных, который полезен для операций проверки принадлежности, массового удаления и других операций, ориентированных на ключи.

Внутренняя механика работы

Архитектура представления:

keySet реализуется как специализированный Set, который делегирует все операции родительской Map. Критически важным аспектом является то, что операции удаления через keySet непосредственно влияют на исходную Map.

Процесс итерации:
Итератор keySet извлекает только ключи, пропуская значения.

Это может быть более эффективно в сценариях, где значения не нужны:
В HashMap: Итератор обходит ту же структуру бакетов, что и entrySet, но возвращает только ключевую компоненту
В TreeMap: Обход дерева выполняется аналогично entrySet, но с извлечением только ключей
В LinkedHashMap: Следование по связному списку с возвратом ключей


Операция удаления через итератор:
При вызове remove() итератора keySet происходит удаление соответствующей пары "ключ-значение" из Map. Этот процесс требует локализации и удаления всего узла, а не только ключа.

Особенности производительности
Эффективность обхода: keySet может быть более эффективен, чем entrySet, когда требуются только ключи, так как избегает создания объектов Map.Entry и извлечения значений.
Операции массового удаления: Методы removeAll() и retainAll() в keySet оптимизированы для работы с ключами и могут быть более эффективны, чем эквивалентные операции через entrySet.
Потребление памяти: keySet обычно создает меньше временных объектов во время итерации по сравнению с entrySet.



Метод values()

Метод values() возвращает представление значений Map в виде Collection. Это представление фокусируется исключительно на значениях, предоставляя view, которое полезно для операций обработки значений, статистического анализа и преобразований.

Внутренняя механика работы

Архитектура представления:
values возвращает Collection, а не Set, поскольку значения могут содержать дубликаты. Эта коллекция поддерживает только операции итерации и удаления, но не добавления, так как значения не могут существовать без ключей.

Процесс итерации:

Итератор values извлекает только значения, что может быть наиболее эффективно в сценариях, где требуются исключительно значения:
В HashMap: Итератор проходит по бакетам и цепочкам, извлекая только value компоненту узлов
В TreeMap: Обход дерева с возвратом значений в порядке сортировки ключей
В LinkedHashMap: Следование по списку с извлечением значений


Особенности модификации:
Коллекция values поддерживает удаление элементов через итератор и методы коллекции. Однако операция удаления по значению требует поиска соответствующего ключа, что может быть затратным.

Особенности производительности
Эффективность для value-oriented операций: values является наиболее эффективным представлением для операций, ориентированных исключительно на значения, таких как статистические вычисления, агрегации и преобразования.
Сложность операций удаления: Удаление по значению требует поиска ключа, ассоциированного с данным значением, что может иметь сложность O(n) в худшем случае.
Отсутствие гарантий уникальности: Поскольку значения могут дублироваться, итерация через values может возвращать повторяющиеся элементы.



Сравнительный анализ представлений

Производительность итерации

Временная сложность:
Все три представления имеют одинаковую асимптотическую сложность O(n) для полного обхода, но различаются константными множителями:
entrySet: Наиболее универсален, но создает наибольшее количество временных объектов
keySet: Более эффективен при работе только с ключами, уменьшает overhead
values: Наиболее эффективен при работе только со значениями


Потребление памяти:
entrySet: Создает временные объекты Map.Entry
keySet: Минимальное потребление памяти при итерации
values: Сравнимо с keySet по потреблению памяти


#Java #для_новичков #beginner #Map #entrySet #keySet #values
Семантика модификаций

Влияние на исходную Map:
Все три представления предоставляют live view, и модификации через них непосредственно влияют на исходную Map:
Удаление через любой итератор удаляет соответствующую пару из Map
Изменение значений через entrySet изменяет значения в Map
Очистка представления очищает исходную Map


Ограничения модификаций:

entrySet: Поддерживает модификацию значений через Map.Entry.setValue()
keySet: Поддерживает только удаление элементов
values: Поддерживает только удаление элементов



Специфика реализации в различных Map

HashMap и связанные реализации

Структура итератора:
Итераторы в HashMap должны обрабатывать сложную структуру данных, включающую массив бакетов, связные списки и деревья.

Процесс итерации включает:
Поиск следующего непустого бакета
Навигацию по цепочке коллизий (список или дерево)
Обработку структурных изменений во время итерации


Механизм fail-fast:
Итераторы HashMap используют счетчик modCount для обнаружения структурных изменений во время итерации. При обнаружении неавторизованной модификации выбрасывается ConcurrentModificationException.

Оптимизации Java 8+:
В современных версиях HashMap итераторы эффективно работают с hybrid структурами, автоматически адаптируясь к спискам и деревьям.


TreeMap

Упорядоченная итерация:


TreeMap обеспечивает обход элементов в sorted порядке, что достигается через:
Inorder traversal красно-черного дерева
Эффективные алгоритмы навигации между узлами
Поддержку descending итераторов

Балансировка и итерация:
Процесс итерации должен корректно работать в условиях ongoing балансировки дерева, обеспечивая consistency обхода.


LinkedHashMap

Итерация с сохранением порядка:
LinkedHashMap гарантирует итерацию в порядке добавления или доступа, что реализуется через:
Следование по двусвязному списку
Поддержку access-order при итерации
Эффективное обновление порядка при операциях доступа



ConcurrentHashMap


Потокобезопасная итерация:
ConcurrentHashMap предоставляет weakly consistent итераторы, которые:
Не выбрасывают ConcurrentModificationException
Могут отражать только часть изменений, произошедших после создания итератора
Обеспечивают высокую производительность в многопоточной среде


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


Потокобезопасность и concurrent модификации

Модель fail-fast

Большинство несинхронизированных реализаций Map используют fail-fast итераторы, которые:
Выбрасывают ConcurrentModificationException при обнаружении структурных изменений
Основаны на сравнении счетчика modCount
Обеспечивают раннее обнаружение ошибок синхронизации


Weakly consistent итераторы
ConcurrentHashMap и другие concurrent реализации используют weakly consistent итераторы, которые:
Не гарантируют отражение всех последних изменений
Не выбрасывают исключения при concurrent модификациях
Обеспечивают баланс между performance и consistency


#Java #для_новичков #beginner #Map #entrySet #keySet #values
Что выведет код?

import java.util.HashMap;
import java.util.Map;

public class Task131125 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);

map.keySet().remove("a");
map.values().remove(2);
map.entrySet().removeIf(entry -> entry.getKey().equals("c"));

System.out.println(map.size());
System.out.println(map.get("a"));
System.out.println(map.get("b"));
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
22%
0 null null
44%
1 null 2
11%
0 null 2
22%
1 null null
Вопрос с собеседований

Что такое REST и его принципы? 🤓


Ответ:

REST
— архитектурный стиль, основанный на HTTP.

Он использует стандартные методы (GET, POST, PUT, DELETE), работает со статeless-сессиями и возвращает ресурсы в виде JSON или XML.

Главные принципы — унифицированный интерфейс и отсутствие состояния.



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История IT-технологий сегодня — 15 ноября


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

Григорий Самуилович Цейтин (15 ноября 1936 года, Ленинград — 27 августа 2022 года, Кэмпбелл, Калифорния, США) — советский и американский учёный-математик и специалист по теории вычислимости; известен Tseitin-преобразованием (широко используется в преобразовании логических формул для SAT-солверов) и работами по тематике Algol-68.


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

1971 — фирма «Intel» выпустила свой первый микропроцессор — модель 4004.


#Biography #Birth_Date #Events #15Ноября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ну что устроим завтра встречу?

Вам интересно?

👍 - если придёте)
👍6
История IT-технологий сегодня — 16 ноября


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

Дэвид Паттерсон (англ. David A. Patterson, 16 ноября 1947 года, Эвергрин-Парк[англ.], Иллинойс) — американский учёный в области архитектуры вычислительных систем; один из авторов идеи RISC, соавтор работ по RAID и многим фундаментальным исследованиям по архитектуре процессоров (лауреат премии Тьюринга).

Кристофер С. Стрейчи (16 ноября 1916 г. – 18 мая 1975 г.) — британский пионер в теории программирования и семантике языков; один из основателей денотационной семантики и ранний разработчик концепций time-sharing и языковых абстракций.


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

1965 — в СССР запущена автоматическая межпланетная станция «Венера-3», беспилотный космический корабль, который первым достиг поверхности Венеры (врезался в неё). Он стал первым земным аппаратом, достигшим поверхности другой планеты.


#Biography #Birth_Date #Events #16Ноября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
JOOQ. Взаимодействуй с БД по-новому.

В сегодняшнем видео мы познакомились с библиотекой взаимодействия с БД - JOOQ.

🔵Рассмотрели чем JOOQ отличается от JPA/Hibernate
🔵Разобрали как JOOQ работает.
🔵Написали демонстрационный код, разобрали как генерируются файлы.
🔵Как всегда немного подебажил))

Репозиторий на GitHub ждет Ваших звезд ☺️

Ссылка на Youtube
Ссылка на Рутьюб

Смотрите, ставьте лайки, подписывайтесь на каналы!✌️
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
История IT-технологий сегодня — 17 ноября


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

Дэвид Паттерсон (англ. David A. Patterson, 16 ноября 1947 года, Эвергрин-Парк[англ.], Иллинойс) — американский учёный в области архитектуры вычислительных систем; один из авторов идеи RISC, соавтор работ по RAID и многим фундаментальным исследованиям по архитектуре процессоров (лауреат премии Тьюринга).

Кристофер С. Стрейчи (16 ноября 1916 г. – 18 мая 1975 г.) — британский пионер в теории программирования и семантике языков; один из основателей денотационной семантики и ранний разработчик концепций time-sharing и языковых абстракций.


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

2006 — в США поступила в продажу игровая консоль 7-го поколения «Sony Playstation 3».


#Biography #Birth_Date #Events #17Ноября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Определение схемы в GraphQL (SDL)

SDL (Schema Definition Language) — это декларативный язык описания GraphQL-схем.
Он задаёт структуру данных и операций, доступных клиенту.
SDL не содержит логики — это контракт, который определяет «форму» API: какие типы есть, какие поля у них доступны, какие аргументы принимаются.

GraphQL-сервер использует SDL как единый источник правды для валидации запросов и построения выполнения.



1. Основные виды типов в SDL

GraphQL предоставляет несколько видов типов, каждый из которых отвечает за свою роль.

1. type — объектный тип (основа схемы)

Используется для описания сущностей:
type User {
id: ID!
name: String!
posts: [Post!]!
}

Типы описывают структуру данных — аналог классов/DTO.


2. input — тип вводимых данных

Используется для аргументов мутаций или сложных параметров запросов.
Отличается от type тем, что не может содержать резолверов и нельзя ссылаться на type с циклом.

input CreateUserInput {
name: String!
age: Int
}


3. enum — перечисления

Хороший способ ограничить варианты.
enum Role {
ADMIN
USER
GUEST
}


4. interface — абстрактный тип

Позволяет описывать общий контракт нескольких типов.
interface Entity {
id: ID!
}

type User implements Entity {
id: ID!
name: String!
}

type Post implements Entity {
id: ID!
title: String!
}

Клиент может запросить id для любого, кто реализует Entity.


5. union — объединение разных типов

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

union SearchResult = User | Post | Comment



2. Как выглядит схема GraphQL


В GraphQL схема определяется набором корневых операций:
Query — чтение
Mutation — изменение
Subscription — события/стриминг


Пример минимальной структуры:
schema {
query: Query
mutation: Mutation
}

На практике «schema {}» часто опускают — сервер выводит её автоматически.


3. Полный пример схемы: пользователи, посты и комментарии

Ниже — типичная схема блог-платформы, написанная в чистом SDL.
Сущности
type User {
id: ID!
name: String!
role: Role!
posts: [Post!]!
}

type Post {
id: ID!
title: String!
content: String
author: User!
comments: [Comment!]!
}

type Comment {
id: ID!
text: String!
author: User!
}

Перечисления
enum Role {
ADMIN
USER
GUEST
}

Входные данные
input CreatePostInput {
title: String!
content: String
}

Запросы
type Query {
user(id: ID!): User
users: [User!]!

post(id: ID!): Post
posts(limit: Int, authorId: ID): [Post!]!
}

Мутации
type Mutation {
createPost(input: CreatePostInput!): Post!
deletePost(id: ID!): Boolean!
}

Подписки
type Subscription {
postCreated: Post!
}



#Java #middle #GraphQL
👍3
4. Как схема связана с кодом

SDL — декларация.
Сервер должен сопоставить поля типам данных и резолверам.


Java (graphql-java, Spring for GraphQL)

SDL:
type Query {
user(id: ID!): User
}


Резолвер:
@Component
public class UserResolver implements GraphQLQueryResolver {
private final UserService service;

public UserResolver(UserService service) {
this.service = service;
}

public User user(Long id) {
return service.findById(id);
}
}


GraphQL автоматически соединяет:
поле user → метод user класса UserResolver
аргумент id → параметр метода


На что важно смотреть в связке схема - код

SDL описывает только форму данных, не логику.
Все поля объектных типов должны иметь резолверы (кроме простых полей, которые GraphQL просто читает из объекта).
input использует DTO-классы.
enum маппится на Enum-класс.
union и interface требуют регистрации type resolver-а.



5. Эволюция схемы: изменение и поддержка версий

GraphQL спроектирован так, чтобы обеспечивать обратную совместимость.
Важный принцип: старые клиенты должны продолжать работать после обновлений.


1. Добавление полей — безопасная операция

Можно безболезненно добавлять:
новые поля в типы
новые аргументы с default value
новые типы
новые enum-значения (если клиенты готовы к неизвестным значениям)


Пример:
type User {
id: ID!
name: String!
email: String # новое поле
}


2. Деприкация полей

Поле нельзя удалить сразу — сначала его помечают как
@deprecated.
type User {
id: ID!
name: String!

# старое поле
username: String @deprecated(reason: "Use 'name' instead")
}


Клиентский код и инструменты разработчика (GraphiQL, GraphQL Codegen) предупредят о деприкации.

3. Удаление полей

Удалять поле можно только после:
уведомления клиентов,
завершения миграции SDK/фронта,
истечения grace-period'a.


4. Эволюция enum-ов

Добавлять значения — безопасно.
Удалять — нет.


5. Миграции input-типов

Если нужно изменить входные данные:
Старое:
input CreatePostInput {
title: String!
}

Новое:
input CreatePostInput {
title: String!
content: String @deprecated(reason: "Use body instead")
body: String
}


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

import java.util.EnumMap;
import java.util.Map;

enum Color { RED, GREEN, BLUE }

public class Task171125 {
public static void main(String[] args) {
Map<Color, String> map = new EnumMap<>(Color.class);

map.put(Color.RED, "red");
map.put(Color.GREEN, null);
map.put(null, "null value");

System.out.println(map.get(Color.RED));
System.out.println(map.get(Color.GREEN));
System.out.println(map.get(null));
System.out.println(map.size());
}
}


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

Что такое autoboxing и unboxing в Java? 🤓


Ответ:

Autoboxing
— автоматическое преобразование примитивного типа в объект-обёртку, а unboxing — обратное действие.

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



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
История IT-технологий сегодня — 18 ноября


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

Пол В. Мокапетрис (родился 18 ноября 1948 года в Бостоне , штат Массачусетс, США) — американский инженер и учёный, создатель системы доменных имён DNS, чья архитектура до сих пор лежит в основе адресации в Интернете.


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

2013 — запущена американская межпланетная станция Mars Atmosphere and Volatile Evolution.


#Biography #Birth_Date #Events #18Ноября
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Раздел 6. Коллекции в Java

Глава 5. Map — отображения (словари)

Практика: В «Библиотеке» создать Map<String, Book> для быстрого поиска книги по названию.

В предыдущих практических статьях мы работали с массивом для хранения книг, Set для уникальных авторов и Queue для очереди читателей. Теперь расширим проект: добавим Map<String, Book> для быстрого поиска книги по названию (title как ключ, объект Book как значение). Это позволит демонстрировать ассоциативный доступ и уникальность ключей в Map. Когда добавляем книгу, она автоматически добавляется в Map; поиск будет происходить по ключу с использованием методов Map.

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

Откройте проект «Библиотека»:
Запустите IntelliJ IDEA и откройте существующий проект LibraryProject. Убедитесь, что классы Book и Library существуют: Book с полями title, author, year (и геттерами, методом printDetails), Library с массивом книг, счетчиком bookCount, методом addBook, Set для авторов и другими методами из прошлых статей.

Импортируйте необходимые пакеты:
В файлах, где будете использовать Map, убедитесь, что импортированы java.util.Map и java.util.HashMap (или другая реализация). IDE подскажет, когда вы начнете писать код — используйте Ctrl+Enter для автодобавления импорта.
Выберите реализацию Map: Для этого используйте HashMap<String, Book> — это базовая реализация для быстрого поиска без порядка. Если хотите поэкспериментировать, попробуйте LinkedHashMap для сохранения порядка вставки книг.


Обновление класса Book (если нужно)
Класс Book уже имеет поле title типа String, которое будет ключом в Map. Если у вас нет геттера для title, добавьте его — он может пригодиться для проверок.

Добавьте геттер для title:
Откройте файл Book.java.
Добавьте публичный метод getTitle(), который возвращает значение поля title.
Это обеспечит инкапсуляцию и позволит получать ключ для Map.



Интеграция Map в класс Library

Map будет храниться в классе Library, чтобы ассоциировать названия книг с объектами Book для быстрого поиска.

Добавьте поле для Map<String, Book>:
Откройте файл Library.java.
Объявите приватное поле bookMap типа Map<String, Book>, инициализированное как new HashMap<> (или LinkedHashMap<>).
Это отображение будет использовать title как ключ (String) и объект Book как значение.


Обновите метод addBook(Book book):
В методе addBook, после добавления книги в массив (books[bookCount] = book; bookCount++;), добавьте пару в Map.
Получите title из книги (через getTitle()).
Используйте put(title, book) для добавления в bookMap.
Проверьте, существует ли уже ключ с помощью containsKey(title): Если да, выведите сообщение "Книга с таким названием уже существует, обновляем" (put перезапишет значение).
Если массив переполнен, не добавляйте в Map — обработайте ошибку (например, выведите сообщение).


Создайте публичный метод findBookByTitle(String title), который:
Использует containsKey(title) для проверки наличия книги в bookMap.
Если ключ существует — возвращает объект Book с помощью get(title) и, optionally, вызывает printDetails() на нем или выводит сообщение "Книга найдена".
Если не существует — выводит сообщение "Книга не найдена" и возвращает null (или бросает исключение, если хотите).


Это продемонстрирует быстрый поиск по ключу.

Обработайте удаление книги (опционально):

Если в проекте есть метод для удаления книги (например, removeBookByTitle(String title)), добавьте remove(title) из bookMap после удаления из массива.
Это обеспечит consistency между массивом и Map.



Обновление класса Main для тестирования

Теперь протестируем Map в Main, добавив книги и выполнив поиск.

Создайте объекты и добавьте книги:
В методе main создайте объект Library.
Создайте несколько объектов Book с разными title (некоторые с одинаковыми, чтобы проверить уникальность ключей — Map перезапишет).
Вызовите addBook для каждой книги — Map заполнится автоматически.
Протестируйте поиск:
Вызовите findBookByTitle с существующим title — должна вывести детали книги.
Вызовите с несуществующим title — сообщение о ненахождении.
Вызовите с title, который был перезаписан — должна вернуться последняя версия книги.


Протестируйте обновление:
Добавьте книгу с существующим title — Map обновит значение, выведите сообщение в addBook.


Тестирование и отладка

После реализации протестируйте, чтобы убедиться в правильной работе Map.

Запустите проект:
Правой кнопкой на Main.java → Run 'Main.main()'.
В консоли увидите сообщения о добавлении и результаты поиска (детали книг или "не найдена").


Проверьте уникальность ключей:
Добавьте две книги с одним title — в Map должна остаться последняя, и поиск вернет её.

Отладка:
Установите breakpoint в методе addBook перед put и после — шагайте (F8) и смотрите размер Map (bookMap.size()) и значение по ключу (bookMap.get(title)).
Если ошибки: NullPointerException (если Map не инициализировано или title null) — добавьте проверки if (title != null && !title.isEmpty()).
ClassCastException — если типы не совпадают (но с generics маловероятно).


Эксперименты:
Измените реализацию Map на LinkedHashMap — проверьте, сохраняется ли порядок ключей при итерации (если добавите цикл по keySet() в print метод).
Попробуйте TreeMap — добавьте Comparator, если нужно сортировать по title (TreeMap требует Comparable для ключей).



Полезные советы для новичков
Инициализация Map: Всегда инициализируйте в конструкторе Library (bookMap = new HashMap<>();), чтобы избежать NullPointerException.
Проверка перед put: Используйте containsKey(title) для логики (если ключ существует, можно предупредить или обновить).
Null-ключи: Избегайте null в title — добавьте проверку в addBook (if (title == null) return;).
Расширение проекта: Подумайте о методе listAllBooks(), который итерирует по values() Map и вызывает printDetails на каждой книге.
Массив vs Map: Заметьте, как Map упрощает поиск по сравнению с перебором массива — это преимущество ассоциативного доступа.



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

Задача 1: Добавьте в Library метод updateBook(String title, Book newBook), который использует containsKey для проверки и put для обновления, если книга существует.
Задача 2: В addBook добавьте проверку: Если title уже в Map, не добавляйте в массив, а обновите значение в Map и выведите "Книга обновлена".
Задача 3: В Main добавьте 4-5 книг, включая дубликат по title, протестируйте поиск и обновление — убедитесь, что Map хранит уникальные ключи.



#Java #для_новичков #beginner #Map #Practice