Какой из реализаций Map вам приходилось пользоваться чаще всего?
  Anonymous Poll
    87%
    HashMap
      
    7%
    LinkedHashMap
      
    0%
    TreeMap
      
    0%
    Hashtable
      
    3%
    ConcurrentHashMap
      
    0%
    IdentityHashMap
      
    0%
    WeakHashMap
      
    3%
    EnumMap
      
    👍1
  Раздел 6. Коллекции в Java
Глава 5. Map — отображения (словари)
Интерфейс Map<K, V> — это часть Java Collections Framework (JCF) из пакета java.util, который представляет структуру для хранения ассоциативных данных. В отличие от других коллекций, таких как List или Set, которые хранят отдельные элементы, Map хранит пары, где каждый ключ (K) связан с значением (V). Это позволяет быстро находить значение по ключу, как в словаре или телефонной книге.
Основные понятия:
Ключ (Key): Уникальный идентификатор для доступа к значению. Ключи не могут дублироваться — если добавить пару с существующим ключом, значение перезапишется.
Значение (Value): Данные, ассоциированные с ключом. Значения могут дублироваться.
Пара (Entry): Единица хранения в Map — комбинация ключа и значения.
Map моделирует математическое отображение (mapping), где каждый ключ maps to ровно одно значение. Это делает Map идеальным для сценариев, где нужна ассоциация, например, ID пользователя — профиль, слово — перевод.
Отличия от Collection:
Map не расширяет Collection<E> — это отдельная ветвь JCF.
Collection — последовательность элементов, Map — ассоциативный массив.
В Map нет индексации (нет get(int index)), доступ только по ключу.
Размер Map — количество пар, не элементов.
Generics в Map: <K, V> обеспечивает типобезопасность: ключи одного типа (например, Integer), значения другого (String). Без generics (raw Map) — устарело и небезопасно.
Хранение пар «ключ–значение»: Особенности
Map хранит данные в форме пар, где ключ — уникальный, а значение — связанное с ним. Это позволяет эффективно решать задачи поиска и ассоциации.
Уникальность ключей:
Ключи всегда уникальны: Map не позволяет дубликаты ключей. Если ключ уже существует, значение обновляется.
Уникальность определяется методами equals() и hashCode() (в hash-based реализациях) или compareTo() (в sorted).
Нюанс: Для custom ключей обязательно переопределите equals() и hashCode() — иначе уникальность по ссылке, не по значению.
Дубликаты значений:
Значения могут повторяться: Несколько ключей могут ссылаться на одно значение.
Нюанс: Если значение — mutable объект, изменения в одном месте отразятся везде (по ссылке).
Null в Map:
Ключи: Большинство реализаций позволяют один null-ключ (HashMap, LinkedHashMap), но TreeMap — нет (NullPointerException).
Значения: Null разрешен всегда.
Порядок в Map:
В общем случае нет (зависит от реализации): Не полагайтесь на порядок пар.
Нюанс: Map не упорядочен, как List, но некоторые реализации добавляют порядок.
Размер и емкость:
Размер (size()) — количество пар.
Емкость: В hash-based — initial capacity и load factor (например, 0.75 — при заполнении >75% ресайз).
Производительность:
В среднем O(1) для доступа по ключу в hash-based, O(log n) в tree-based.
Нюанс: Зависит от качества hashCode() — плохие хэши приводят к деградации до O(n).
Полезные советы для новичков
Выбор типов K/V: Ключи — immutable (String, Integer), чтобы избежать изменений, влияющих на хэш.
Custom ключи: Переопределяйте equals/hashCode (IDE поможет: Generate → equals() and hashCode()).
Map vs другие коллекции: Используйте Map для ассоциаций, Set для уникальных элементов, List для последовательностей.
#Java #для_новичков #beginner #Map
Глава 5. Map — отображения (словари)
Интерфейс Map<K, V> — это часть Java Collections Framework (JCF) из пакета java.util, который представляет структуру для хранения ассоциативных данных. В отличие от других коллекций, таких как List или Set, которые хранят отдельные элементы, Map хранит пары, где каждый ключ (K) связан с значением (V). Это позволяет быстро находить значение по ключу, как в словаре или телефонной книге.
Основные понятия:
Ключ (Key): Уникальный идентификатор для доступа к значению. Ключи не могут дублироваться — если добавить пару с существующим ключом, значение перезапишется.
Значение (Value): Данные, ассоциированные с ключом. Значения могут дублироваться.
Пара (Entry): Единица хранения в Map — комбинация ключа и значения.
Map моделирует математическое отображение (mapping), где каждый ключ maps to ровно одно значение. Это делает Map идеальным для сценариев, где нужна ассоциация, например, ID пользователя — профиль, слово — перевод.
Отличия от Collection:
Map не расширяет Collection<E> — это отдельная ветвь JCF.
Collection — последовательность элементов, Map — ассоциативный массив.
В Map нет индексации (нет get(int index)), доступ только по ключу.
Размер Map — количество пар, не элементов.
Generics в Map: <K, V> обеспечивает типобезопасность: ключи одного типа (например, Integer), значения другого (String). Без generics (raw Map) — устарело и небезопасно.
Хранение пар «ключ–значение»: Особенности
Map хранит данные в форме пар, где ключ — уникальный, а значение — связанное с ним. Это позволяет эффективно решать задачи поиска и ассоциации.
Уникальность ключей:
Ключи всегда уникальны: Map не позволяет дубликаты ключей. Если ключ уже существует, значение обновляется.
Уникальность определяется методами equals() и hashCode() (в hash-based реализациях) или compareTo() (в sorted).
Нюанс: Для custom ключей обязательно переопределите equals() и hashCode() — иначе уникальность по ссылке, не по значению.
Дубликаты значений:
Значения могут повторяться: Несколько ключей могут ссылаться на одно значение.
Нюанс: Если значение — mutable объект, изменения в одном месте отразятся везде (по ссылке).
Null в Map:
Ключи: Большинство реализаций позволяют один null-ключ (HashMap, LinkedHashMap), но TreeMap — нет (NullPointerException).
Значения: Null разрешен всегда.
Порядок в Map:
В общем случае нет (зависит от реализации): Не полагайтесь на порядок пар.
Нюанс: Map не упорядочен, как List, но некоторые реализации добавляют порядок.
Размер и емкость:
Размер (size()) — количество пар.
Емкость: В hash-based — initial capacity и load factor (например, 0.75 — при заполнении >75% ресайз).
Производительность:
В среднем O(1) для доступа по ключу в hash-based, O(log n) в tree-based.
Нюанс: Зависит от качества hashCode() — плохие хэши приводят к деградации до O(n).
Полезные советы для новичков
Выбор типов K/V: Ключи — immutable (String, Integer), чтобы избежать изменений, влияющих на хэш.
Custom ключи: Переопределяйте equals/hashCode (IDE поможет: Generate → equals() and hashCode()).
Map vs другие коллекции: Используйте Map для ассоциаций, Set для уникальных элементов, List для последовательностей.
#Java #для_новичков #beginner #Map
👍4
  Что выведет код?
#Tasks
import java.util.HashMap;
import java.util.Map;
public class Task291025 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("a", 3);
map.putIfAbsent("b", 4);
map.putIfAbsent("c", 5);
System.out.println(map.get("a"));
System.out.println(map.get("b"));
System.out.println(map.get("c"));
System.out.println(map.getOrDefault("d", 6));
}
}
#Tasks
👍2
  👍2
  Вопрос с собеседований
Что такое strong, soft, weak и phantom ссылки?🤓 
Ответ:
Strong — обычная ссылка, объект не собирается GC.
Soft — GC удалит объект при нехватке памяти.
Weak — GC удалит при первой возможности.
Phantom — используется для отслеживания удаления объекта. Эти типы ссылок помогают управлять кэшами и жизненным циклом объектов. 
#собеседование
Что такое strong, soft, weak и phantom ссылки?
Ответ:
Strong
Soft — GC удалит объект при нехватке памяти.
Weak — GC удалит при первой возможности.
Phantom — используется для отслеживания удаления объекта. Эти типы ссылок помогают управлять кэшами и жизненным циклом объектов.
#собеседование
Please open Telegram to view this post
    VIEW IN TELEGRAM
  👍4
  История IT-технологий сегодня — 30 октября
ℹ️  Кто родился в этот день
Андре́й Никола́евич Ти́хонов (17 [30] октября 1906, Гжатск (в настоящее время город Гагарин) Смоленской губернии — 7 октября 1993, Москва) — советский математик и геофизик, академик Академии наук СССР, дважды Герой Социалистического Труда. Основатель факультета вычислительной математики и кибернетики МГУ.
Карло Генрих Сейкин (родился 30 октября 1941 года) — швейцарско-американский компьютерный учёный, профессор Университета Калифорнии, Беркли; пионер в области архитектуры процессоров, компьютерной графики и CAD-инструментов для проектирования электронных схем.
 🌐  Знаковые события
1907 — русский физик Борис Розинг в ответ на поданную им 25 июля заявку получил патент № 18076 на «Способ электрической передачи изображений на расстояние», то есть телевидение.
#Biography #Birth_Date #Events #30Октября
Андре́й Никола́евич Ти́хонов (17 [30] октября 1906, Гжатск (в настоящее время город Гагарин) Смоленской губернии — 7 октября 1993, Москва) — советский математик и геофизик, академик Академии наук СССР, дважды Герой Социалистического Труда. Основатель факультета вычислительной математики и кибернетики МГУ.
Карло Генрих Сейкин (родился 30 октября 1941 года) — швейцарско-американский компьютерный учёный, профессор Университета Калифорнии, Беркли; пионер в области архитектуры процессоров, компьютерной графики и CAD-инструментов для проектирования электронных схем.
1907 — русский физик Борис Розинг в ответ на поданную им 25 июля заявку получил патент № 18076 на «Способ электрической передачи изображений на расстояние», то есть телевидение.
#Biography #Birth_Date #Events #30Октября
Please open Telegram to view this post
    VIEW IN TELEGRAM
  👍3
  Как вы себя оцениваете по грейду?
  Anonymous Poll
    56%
    Я наверно даже не джун
      
    28%
    Я точно джун
      
    6%
    Я уверенный мидл
      
    9%
    Сеньор я
      
    👍1
  Архитектура gRPC: как всё работает под капотом
gRPC — это современный фреймворк удалённого вызова процедур (RPC, Remote Procedure Call), разработанный Google. Он позволяет приложениям общаться друг с другом как будто они вызывают локальные функции, хотя на самом деле взаимодействие идёт по сети. Чтобы понять, почему gRPC так эффективен, нужно разобрать его архитектуру и то, что происходит «под капотом».
1. Концепция gRPC: RPC-модель нового поколения
RPC (Remote Procedure Call) — это подход, при котором одна программа может вызвать функцию, которая физически исполняется на другом сервере.
В классической модели RPC разработчик просто вызывает метод, а инфраструктура берёт на себя всё — упаковку данных, передачу по сети и распаковку на другой стороне.
gRPC реализует эту идею, но в современном, высокопроизводительном виде — поверх HTTP/2 и с использованием Protocol Buffers для сериализации.
2. Основные участники архитектуры
Клиент (Client)
Это программа, которая инициирует вызов удалённого метода. Она не знает деталей того, как сервер устроен внутри.
Клиент работает с client stub — это локальный объект, который выглядит как обычный класс с методами, но при вызове каждого метода на самом деле выполняется сетевое обращение к серверу.
Сервер (Server)
Это приложение, которое реализует интерфейс, описанный в .proto файле. Сервер принимает запросы от клиентов, обрабатывает их и отправляет ответы.
Client Stub и Server Stub
Что такое Stub
Stub — это «заглушка», или точнее — сгенерированный код, который связывает ваш код с gRPC-инфраструктурой.
Client Stub (клиентская заглушка) — это класс, который содержит методы, соответствующие сервисам, определённым в .proto.
Когда вы вызываете метод stub.buyCar(request), gRPC автоматически:
Сериализует объект request в бинарный формат.
Отправляет его по сети через HTTP/2.
Получает ответ, десериализует и возвращает его как обычный объект Java.
Server Stub — это абстрактный класс, который вы расширяете, чтобы реализовать свою бизнес-логику. Он автоматически принимает входящие вызовы, десериализует данные и вызывает ваш метод.
Пример:
После генерации protoc создаёт классы:
Реализация сервера:
Клиент:
#Java #middle #gRPC
gRPC — это современный фреймворк удалённого вызова процедур (RPC, Remote Procedure Call), разработанный Google. Он позволяет приложениям общаться друг с другом как будто они вызывают локальные функции, хотя на самом деле взаимодействие идёт по сети. Чтобы понять, почему gRPC так эффективен, нужно разобрать его архитектуру и то, что происходит «под капотом».
1. Концепция gRPC: RPC-модель нового поколения
RPC (Remote Procedure Call) — это подход, при котором одна программа может вызвать функцию, которая физически исполняется на другом сервере.
В классической модели RPC разработчик просто вызывает метод, а инфраструктура берёт на себя всё — упаковку данных, передачу по сети и распаковку на другой стороне.
gRPC реализует эту идею, но в современном, высокопроизводительном виде — поверх HTTP/2 и с использованием Protocol Buffers для сериализации.
2. Основные участники архитектуры
Клиент (Client)
Это программа, которая инициирует вызов удалённого метода. Она не знает деталей того, как сервер устроен внутри.
Клиент работает с client stub — это локальный объект, который выглядит как обычный класс с методами, но при вызове каждого метода на самом деле выполняется сетевое обращение к серверу.
Сервер (Server)
Это приложение, которое реализует интерфейс, описанный в .proto файле. Сервер принимает запросы от клиентов, обрабатывает их и отправляет ответы.
Client Stub и Server Stub
Что такое Stub
Stub — это «заглушка», или точнее — сгенерированный код, который связывает ваш код с gRPC-инфраструктурой.
Client Stub (клиентская заглушка) — это класс, который содержит методы, соответствующие сервисам, определённым в .proto.
Когда вы вызываете метод stub.buyCar(request), gRPC автоматически:
Сериализует объект request в бинарный формат.
Отправляет его по сети через HTTP/2.
Получает ответ, десериализует и возвращает его как обычный объект Java.
Server Stub — это абстрактный класс, который вы расширяете, чтобы реализовать свою бизнес-логику. Он автоматически принимает входящие вызовы, десериализует данные и вызывает ваш метод.
Пример:
// .proto файл
syntax = "proto3";
service CarService {
rpc BuyCar (CarRequest) returns (CarResponse);
}
message CarRequest {
string model = 1;
int32 budget = 2;
}
message CarResponse {
string status = 1;
}
После генерации protoc создаёт классы:
CarServiceGrpc.CarServiceImplBase — Server Stub
CarServiceGrpc.CarServiceBlockingStub и CarServiceGrpc.CarServiceFutureStub — Client Stubs
Реализация сервера:
public class CarServiceImpl extends CarServiceGrpc.CarServiceImplBase {
    @Override
    public void buyCar(CarRequest request, StreamObserver<CarResponse> responseObserver) {
        String result = "You bought: " + request.getModel();
        CarResponse response = CarResponse.newBuilder()
            .setStatus(result)
            .build();
        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }
}Клиент:
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8080)
        .usePlaintext()
        .build();
CarServiceGrpc.CarServiceBlockingStub stub = CarServiceGrpc.newBlockingStub(channel);
CarRequest request = CarRequest.newBuilder()
        .setModel("Tesla Model 3")
        .setBudget(50000)
        .build();
CarResponse response = stub.buyCar(request);
System.out.println(response.getStatus());#Java #middle #gRPC
👍2
  3. Роль Protocol Buffers (protobuf)
Protocol Buffers — это бинарный формат сериализации данных, разработанный Google. Он выполняет две функции:
Описание структуры данных (через .proto файл).
Это аналог схемы JSON или XML, но строгий и типизированный.
Сериализация и десериализация (преобразование объектов в компактную бинарную форму и обратно).
Пример .proto файла не только описывает сообщения, но и определяет сервис (то есть API интерфейс).
Почему protobuf — ключевой элемент:
Он компактен: бинарный формат в несколько раз меньше JSON.
Он типобезопасен: при компиляции проверяются типы.
Он быстр: сериализация и десериализация работают на уровне байтов, без парсинга текста.
4. Как происходит сериализация и десериализация
Сериализация — это процесс превращения объекта в поток байтов для передачи по сети.
Десериализация — обратный процесс.
В gRPC:
Клиент вызывает метод stub.method(request).
request сериализуется с помощью Protocol Buffers в бинарный поток.
Поток отправляется через HTTP/2.
Сервер принимает поток, десериализует его обратно в объект CarRequest.
После обработки сервер сериализует ответ (CarResponse) и отправляет обратно.
Важно: gRPC сам управляет сериализацией. Вам не нужно ничего кодировать вручную — всё делает сгенерированный stub.
5. Что делает protoc и зачем нужны плагины
protoc — это компилятор Protocol Buffers. Он принимает .proto файл и генерирует исходный код для нужного языка.
Например:
gRPC добавляет ещё один плагин — --grpc-java_out, который генерирует код для stub'ов.
Таким образом, protoc создаёт:
Классы-сообщения (CarRequest, CarResponse)
gRPC классы (CarServiceGrpc, Stub и ImplBase)
Для каждого языка есть свой плагин:
--grpc-java_out для Java
--grpc-python_out для Python
--grpc-go_out для Go
и т. д.
Это и есть причина, почему gRPC мультиплатформенный — интерфейс описывается один раз в .proto, а код для всех языков генерируется автоматически.
6. Почему gRPC быстрее REST
gRPC построен поверх HTTP/2, а REST — чаще всего поверх HTTP/1.1. Разница принципиальна.
Ключевые причины производительности:
HTTP/2 поддерживает мультиплексирование — можно отправлять несколько запросов в одном соединении без блокировки.
Сжатие заголовков (HPACK) уменьшает накладные расходы.
Бинарная сериализация (protobuf) — меньше данных, быстрее парсинг.
Постоянное соединение — нет затрат на открытие/закрытие TCP для каждого запроса.
Streaming — можно передавать поток данных, а не ждать полного ответа (например, поток логов или большого файла).
7. Суммарно: что происходит при вызове метода в gRPC
Пошагово:
Клиент вызывает метод stub.someMethod(request).
Stub сериализует объект через protobuf.
Сериализованные данные упаковываются в HTTP/2 фрейм и отправляются на сервер.
Сервер принимает фрейм, десериализует данные.
Вызвается метод реализации (ImplBase).
Сервер формирует ответ, сериализует через protobuf.
Ответ отправляется обратно по тому же соединению.
Клиент получает и десериализует ответ.
Для разработчика — это выглядит как обычный вызов функции.
Под капотом же происходит оптимизированное сетевое взаимодействие с минимальными потерями.
#Java #middle #gRPC
Protocol Buffers — это бинарный формат сериализации данных, разработанный Google. Он выполняет две функции:
Описание структуры данных (через .proto файл).
Это аналог схемы JSON или XML, но строгий и типизированный.
Сериализация и десериализация (преобразование объектов в компактную бинарную форму и обратно).
Пример .proto файла не только описывает сообщения, но и определяет сервис (то есть API интерфейс).
Почему protobuf — ключевой элемент:
Он компактен: бинарный формат в несколько раз меньше JSON.
Он типобезопасен: при компиляции проверяются типы.
Он быстр: сериализация и десериализация работают на уровне байтов, без парсинга текста.
4. Как происходит сериализация и десериализация
Сериализация — это процесс превращения объекта в поток байтов для передачи по сети.
Десериализация — обратный процесс.
В gRPC:
Клиент вызывает метод stub.method(request).
request сериализуется с помощью Protocol Buffers в бинарный поток.
Поток отправляется через HTTP/2.
Сервер принимает поток, десериализует его обратно в объект CarRequest.
После обработки сервер сериализует ответ (CarResponse) и отправляет обратно.
Важно: gRPC сам управляет сериализацией. Вам не нужно ничего кодировать вручную — всё делает сгенерированный stub.
5. Что делает protoc и зачем нужны плагины
protoc — это компилятор Protocol Buffers. Он принимает .proto файл и генерирует исходный код для нужного языка.
Например:
protoc --java_out=./build/generated proto/car.proto
gRPC добавляет ещё один плагин — --grpc-java_out, который генерирует код для stub'ов.
protoc --plugin=protoc-gen-grpc-java=path/to/protoc-gen-grpc-java \
--grpc-java_out=./build/generated \
--java_out=./build/generated \
proto/car.proto
Таким образом, protoc создаёт:
Классы-сообщения (CarRequest, CarResponse)
gRPC классы (CarServiceGrpc, Stub и ImplBase)
Для каждого языка есть свой плагин:
--grpc-java_out для Java
--grpc-python_out для Python
--grpc-go_out для Go
и т. д.
Это и есть причина, почему gRPC мультиплатформенный — интерфейс описывается один раз в .proto, а код для всех языков генерируется автоматически.
6. Почему gRPC быстрее REST
gRPC построен поверх HTTP/2, а REST — чаще всего поверх HTTP/1.1. Разница принципиальна.
Ключевые причины производительности:
HTTP/2 поддерживает мультиплексирование — можно отправлять несколько запросов в одном соединении без блокировки.
Сжатие заголовков (HPACK) уменьшает накладные расходы.
Бинарная сериализация (protobuf) — меньше данных, быстрее парсинг.
Постоянное соединение — нет затрат на открытие/закрытие TCP для каждого запроса.
Streaming — можно передавать поток данных, а не ждать полного ответа (например, поток логов или большого файла).
7. Суммарно: что происходит при вызове метода в gRPC
Пошагово:
Клиент вызывает метод stub.someMethod(request).
Stub сериализует объект через protobuf.
Сериализованные данные упаковываются в HTTP/2 фрейм и отправляются на сервер.
Сервер принимает фрейм, десериализует данные.
Вызвается метод реализации (ImplBase).
Сервер формирует ответ, сериализует через protobuf.
Ответ отправляется обратно по тому же соединению.
Клиент получает и десериализует ответ.
Для разработчика — это выглядит как обычный вызов функции.
Под капотом же происходит оптимизированное сетевое взаимодействие с минимальными потерями.
#Java #middle #gRPC
👍2
  Что выведет код?
#Tasks
import java.util.HashMap;
public class Task301025 {
public static void main(String[] args) {
HashMap<Key, String> map = new HashMap<>();
Key k1 = new Key(1);
Key k2 = new Key(1);
Key k3 = new Key(2);
map.put(k1, "first");
map.put(k2, "second");
map.put(k3, "third");
k1.value = 2;
System.out.println(map.get(k1));
System.out.println(map.get(k2));
System.out.println(map.get(k3));
System.out.println(map.size());
}
static class Key {
int value;
Key(int value) { this.value = value; }
public boolean equals(Object o) {
return o instanceof Key && ((Key) o).value == this.value;
}
public int hashCode() {
return value;
}
}
}
#Tasks
👍1
  Варианты ответа:
  Anonymous Quiz
    20%
    second null third 2
      
    20%
    null null third 2
      
    0%
    third null third 2
      
    60%
    second second third 3
      
    👍1
  Вопрос с собеседований
Как работает finalize() и почему его не рекомендуют использовать?🤓 
Ответ:
Метод finalize() вызывается перед удалением объекта GC, но время вызова непредсказуемо. 
Он может задерживать сборку мусора, а ошибки в нём — мешать очистке.
Вместо него применяют try-with-resources или Cleaner/PhantomReference. 
#собеседование
Как работает finalize() и почему его не рекомендуют использовать?
Ответ:
Он может задерживать сборку мусора, а ошибки в нём — мешать очистке.
Вместо него применяют try-with-resources или Cleaner/PhantomReference.
#собеседование
Please open Telegram to view this post
    VIEW IN TELEGRAM
  👍2
  История IT-технологий сегодня — 31 октября
ℹ️  Кто родился в этот день
Не нашел..(
 🌐  Знаковые события
2000 — остановлен последний компьютер, использовавший ОС Multics;
2000 — старт первой российской экспедиции МКС-1 на космическом корабле Союз ТМ-31 к Международной космической станции.
2005 — НАСА объявило об открытии двух естественных спутников Плутона, впоследствии получивших имена Гидра и Никта.
#Biography #Birth_Date #Events #31Октября
Не нашел..(
2000 — остановлен последний компьютер, использовавший ОС Multics;
2000 — старт первой российской экспедиции МКС-1 на космическом корабле Союз ТМ-31 к Международной космической станции.
2005 — НАСА объявило об открытии двух естественных спутников Плутона, впоследствии получивших имена Гидра и Никта.
#Biography #Birth_Date #Events #31Октября
Please open Telegram to view this post
    VIEW IN TELEGRAM
  👍3
  Раздел 6. Коллекции в Java
Глава 5. Map — отображения (словари)
Реализации: HashMap, LinkedHashMap, TreeMap и остальные
JCF предоставляет богатый набор реализаций Map, каждая оптимизирована под конкретные нужды.
Все они реализуют Map<K, V>, но различаются по:
Хранению: Хэш-таблица (HashMap), связный список + хэш (LinkedHashMap), красно-черное дерево (TreeMap).
Порядку: Нет (HashMap), вставки (LinkedHashMap), сортировка по ключам (TreeMap).
Производительности: O(1) для хэш, O(log n) для дерево.
Дополнительно: Специальные для enum, слабых ссылок и т.д.
1. HashMap<K, V>: Основная реализация
Описание: HashMap — сердце Map в Java, основанная на хэш-таблице. Хранит пары в массиве "бакетов" (buckets), где каждый бакет — список узлов (node) с ключом, значением и хэш-кодом.
Внутренняя структура:
Массив Node<K,V>[] table (initial capacity 16, load factor 0.75).
При put: Вычисляет hash = key.hashCode() ^ (hash >>> 16) для равномерности.
Индекс бакета: hash & (table.length - 1).
Коллизия: LinkedList или Tree (с Java 8, если > 8 узлов — дерево для O(log n)).
Ресайз: При >75% заполнения — удваивает размер, перехэширует все элементы.
Big O:
put/get/remove/containsKey: O(1) средний, O(n) worst (плохие хэши).
Итерация: O(capacity).
Особенности:
Порядок: Нет (iteration order не гарантирован).
Null: Один null-ключ, несколько null-значений.
Thread-safe: Нет (ConcurrentModificationException при параллельном доступе).
Initial capacity/load factor: new HashMap<>(16, 0.75f) для оптимизации.
Нюансы и ловушки:
hashCode/equals: Критичны! Плохой hashCode — деградация до O(n). Изменение ключа после put — потеря элемента.
Ресайз: O(n) время, но редко.
Java 8+: Tree nodes для коллизий (>8 узлов).
Remove: Если null-ключ — специальная обработка.
Итерация: entrySet(), keySet(), values() — O(capacity), не size().
Пример кода:
2. LinkedHashMap<K, V>: HashMap с порядком
Описание: Расширение HashMap с двусвязным списком для сохранения порядка вставки (insertion-order) или доступа (access-order для LRU-кэша).
Внутренняя структура: HashMap + Entry с prev/next ссылками. Два режима: INSERTION_ORDER (default) или ACCESS_ORDER (constructor flag).
Big O: O(1) для put/get/remove, как HashMap.
Особенности:
Порядок: Вставки (по умолчанию) или доступа (get/put обновляет позицию).
Null: Да.
Thread-safe: Нет.
Нюансы:
LRU кэш: new LinkedHashMap<>(16, 0.75f, true) — access-order, removeEldestEntry для eviction.
Итерация: В порядке вставки/доступа.
Ресайз: Как HashMap, но сохраняет порядок.
Пример:
#Java #для_новичков #beginner #Map #HashMap #LinkedHashMap #TreeMap #Hashtable #IdentityHashMap #EnumMap #WeakHashMap
Глава 5. Map — отображения (словари)
Реализации: HashMap, LinkedHashMap, TreeMap и остальные
JCF предоставляет богатый набор реализаций Map, каждая оптимизирована под конкретные нужды.
Все они реализуют Map<K, V>, но различаются по:
Хранению: Хэш-таблица (HashMap), связный список + хэш (LinkedHashMap), красно-черное дерево (TreeMap).
Порядку: Нет (HashMap), вставки (LinkedHashMap), сортировка по ключам (TreeMap).
Производительности: O(1) для хэш, O(log n) для дерево.
Дополнительно: Специальные для enum, слабых ссылок и т.д.
1. HashMap<K, V>: Основная реализация
Описание: HashMap — сердце Map в Java, основанная на хэш-таблице. Хранит пары в массиве "бакетов" (buckets), где каждый бакет — список узлов (node) с ключом, значением и хэш-кодом.
Внутренняя структура:
Массив Node<K,V>[] table (initial capacity 16, load factor 0.75).
При put: Вычисляет hash = key.hashCode() ^ (hash >>> 16) для равномерности.
Индекс бакета: hash & (table.length - 1).
Коллизия: LinkedList или Tree (с Java 8, если > 8 узлов — дерево для O(log n)).
Ресайз: При >75% заполнения — удваивает размер, перехэширует все элементы.
Big O:
put/get/remove/containsKey: O(1) средний, O(n) worst (плохие хэши).
Итерация: O(capacity).
Особенности:
Порядок: Нет (iteration order не гарантирован).
Null: Один null-ключ, несколько null-значений.
Thread-safe: Нет (ConcurrentModificationException при параллельном доступе).
Initial capacity/load factor: new HashMap<>(16, 0.75f) для оптимизации.
Нюансы и ловушки:
hashCode/equals: Критичны! Плохой hashCode — деградация до O(n). Изменение ключа после put — потеря элемента.
Ресайз: O(n) время, но редко.
Java 8+: Tree nodes для коллизий (>8 узлов).
Remove: Если null-ключ — специальная обработка.
Итерация: entrySet(), keySet(), values() — O(capacity), не size().
Пример кода:
javaimport java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> ages = new HashMap<>();
ages.put("Алексей", 35);
ages.put("Мария", 28);
ages.put("Алексей", 36); // Перезапись
System.out.println(ages.get("Алексей")); // 36
ages.put(null, 0); // Null-ключ
System.out.println(ages.size()); // 3
// Итерация
for (Map.Entry<String, Integer> entry : ages.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
Когда использовать: 99% случаев — быстрый поиск/кэш (userId -> User).
2. LinkedHashMap<K, V>: HashMap с порядком
Описание: Расширение HashMap с двусвязным списком для сохранения порядка вставки (insertion-order) или доступа (access-order для LRU-кэша).
Внутренняя структура: HashMap + Entry с prev/next ссылками. Два режима: INSERTION_ORDER (default) или ACCESS_ORDER (constructor flag).
Big O: O(1) для put/get/remove, как HashMap.
Особенности:
Порядок: Вставки (по умолчанию) или доступа (get/put обновляет позицию).
Null: Да.
Thread-safe: Нет.
Нюансы:
LRU кэш: new LinkedHashMap<>(16, 0.75f, true) — access-order, removeEldestEntry для eviction.
Итерация: В порядке вставки/доступа.
Ресайз: Как HashMap, но сохраняет порядок.
Пример:
javaimport java.util.LinkedHashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new LinkedHashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("A", 3); // Обновляет, но порядок сохраняется
for (String key : map.keySet()) {
System.out.println(key); // A, B — порядок вставки
}
// Access-order
Map<String, Integer> lru = new LinkedHashMap<>(16, 0.75f, true);
lru.put("A", 1);
lru.get("A"); // "A" перемещается в конец
}
}
Когда использовать: Кэш с порядком (LRU), когда нужен predictable iteration.
#Java #для_новичков #beginner #Map #HashMap #LinkedHashMap #TreeMap #Hashtable #IdentityHashMap #EnumMap #WeakHashMap
👍1
  3. TreeMap<K, V>: Отсортированная Map
Описание: Реализация SortedMap<K, V> на красно-черном дереве (red-black tree). Ключи всегда отсортированы.
Внутренняя структура: Дерево узлов с left/right/child ссылками, цветом для баланса.
Big O: O(log n) для put/get/remove/containsKey.
Особенности:
Порядок: Сортировка по ключам (Comparable или Comparator).
Null-ключ: Нет (NPE).
Null-значение: Да.
Thread-safe: Нет.
Нюансы:
Comparator: new TreeMap<>(comparator) для custom сортировки.
Дополнительные методы: firstKey(), lastKey(), headMap(K to), tailMap(K from), subMap.
Custom ключи: Comparable<K> или Comparator.
Баланс: Автоматический, O(log n) гарантировано.
Пример:
Остальные реализации: Hashtable, IdentityHashMap, EnumMap, WeakHashMap
Hashtable<K, V> (устаревшая)
Описание: Первая Map в Java (1.0), synchronized версия HashMap.
Особенности: Thread-safe (synchronized методы), нет null, порядок нет.
Big O: O(1).
Нюансы: Медленнее HashMap (locks на каждый метод), legacy — используйте ConcurrentHashMap.
Когда: Только legacy код.
IdentityHashMap<K, V>
Описание: HashMap с == вместо equals/hashCode (по ссылке).
Особенности: Для объектов, где важна идентичность (graph algorithms).
Big O: O(1).
Нюансы: Load factor 0.5, double hash для коллизий.
Когда: Редко, для identity сравнения.
EnumMap<K extends Enum<K>, V>
Описание: Оптимизированная Map для enum ключей (массив вместо хэш).
Особенности: O(1), порядок enum, нет null-ключа.
Нюансы: Ключи — enum, values any.
Когда: State machines, enum configs.
WeakHashMap<K, V>
Описание: HashMap с weak keys (GC может удалить entry, если ключ недостижим).
Особенности: Для кэшей, где память критична.
Big O: O(1).
Нюансы: Values strong, cleanup не мгновенный.
Когда: Canonicalizing mappings (interning).
Полезные советы для новичков
HashMap 95% случаев: Начните с неё.
LinkedHashMap для кэша: removeEldestEntry для LRU.
TreeMap для сортировки: Comparator для reverse.
Custom ключи: IDE генерирует equals/hashCode.
Initial capacity: new HashMap<>(expectedSize) для избежания ресайза.
Ошибки: NPE в TreeMap с null-ключом; ClassCast в TreeMap без Comparable.
#Java #для_новичков #beginner #Map #HashMap #LinkedHashMap #TreeMap #Hashtable #IdentityHashMap #EnumMap #WeakHashMap
Описание: Реализация SortedMap<K, V> на красно-черном дереве (red-black tree). Ключи всегда отсортированы.
Внутренняя структура: Дерево узлов с left/right/child ссылками, цветом для баланса.
Big O: O(log n) для put/get/remove/containsKey.
Особенности:
Порядок: Сортировка по ключам (Comparable или Comparator).
Null-ключ: Нет (NPE).
Null-значение: Да.
Thread-safe: Нет.
Нюансы:
Comparator: new TreeMap<>(comparator) для custom сортировки.
Дополнительные методы: firstKey(), lastKey(), headMap(K to), tailMap(K from), subMap.
Custom ключи: Comparable<K> или Comparator.
Баланс: Автоматический, O(log n) гарантировано.
Пример:
javaimport java.util.TreeMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new TreeMap<>();
map.put(3, "Три");
map.put(1, "Один");
map.put(2, "Два");
for (Integer key : map.keySet()) {
System.out.println(key + ": " + map.get(key)); // 1: Один, 2: Два, 3: Три
}
System.out.println(map.firstKey()); // 1
}
}
Когда использовать: Отсортированные ключи (диапазонные запросы, алфавитный словарь).
Остальные реализации: Hashtable, IdentityHashMap, EnumMap, WeakHashMap
Hashtable<K, V> (устаревшая)
Описание: Первая Map в Java (1.0), synchronized версия HashMap.
Особенности: Thread-safe (synchronized методы), нет null, порядок нет.
Big O: O(1).
Нюансы: Медленнее HashMap (locks на каждый метод), legacy — используйте ConcurrentHashMap.
Когда: Только legacy код.
IdentityHashMap<K, V>
Описание: HashMap с == вместо equals/hashCode (по ссылке).
Особенности: Для объектов, где важна идентичность (graph algorithms).
Big O: O(1).
Нюансы: Load factor 0.5, double hash для коллизий.
Когда: Редко, для identity сравнения.
EnumMap<K extends Enum<K>, V>
Описание: Оптимизированная Map для enum ключей (массив вместо хэш).
Особенности: O(1), порядок enum, нет null-ключа.
Нюансы: Ключи — enum, values any.
Когда: State machines, enum configs.
WeakHashMap<K, V>
Описание: HashMap с weak keys (GC может удалить entry, если ключ недостижим).
Особенности: Для кэшей, где память критична.
Big O: O(1).
Нюансы: Values strong, cleanup не мгновенный.
Когда: Canonicalizing mappings (interning).
Полезные советы для новичков
HashMap 95% случаев: Начните с неё.
LinkedHashMap для кэша: removeEldestEntry для LRU.
TreeMap для сортировки: Comparator для reverse.
Custom ключи: IDE генерирует equals/hashCode.
Initial capacity: new HashMap<>(expectedSize) для избежания ресайза.
Ошибки: NPE в TreeMap с null-ключом; ClassCast в TreeMap без Comparable.
#Java #для_новичков #beginner #Map #HashMap #LinkedHashMap #TreeMap #Hashtable #IdentityHashMap #EnumMap #WeakHashMap
👍2
  Что выведет код?
#Tasks
  import java.util.LinkedHashMap;
import java.util.Map;
public class Task311025 {
public static void main(String[] args) {
Map<String, Integer> map = new LinkedHashMap<>(16, 0.75f, true);
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
map.get("a");
map.put("d", 4);
map.get("b");
System.out.println(map.keySet());
}
}
#Tasks
