Идеально для CLI, serverless и микросервисов.
Используй native-image, настраивай reflection-config.json и удивляйся, как твой код запускается быстрее Python-скрипта.Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍4❤3
Когда собираешь Map через Stream API подумай про дубликаты ключей!
В Java часто нужно превратить список объектов в Map.
Например, есть пользователи, и хочется получить словарь id -> name:
Код выглядит нормально, пока в списке нет двух пользователей с одинаковым id.
Если дубликат появится, Java выбросит:
Поэтому, если дубликаты возможны, лучше сразу указать merge-функцию:
Здесь при совпадении ключей останется новое значение.
Можно сделать наоборот:
Тогда сохранится первое значение.
👉 Java Ready | #совет
В Java часто нужно превратить список объектов в Map.
Например, есть пользователи, и хочется получить словарь id -> name:
Map<Long, String> usersById = users.stream()
.collect(Collectors.toMap(User::id, User::name));
Код выглядит нормально, пока в списке нет двух пользователей с одинаковым id.
Если дубликат появится, Java выбросит:
IllegalStateException: Duplicate key
Поэтому, если дубликаты возможны, лучше сразу указать merge-функцию:
Map<Long, String> usersById = users.stream()
.collect(Collectors.toMap(
User::id,
User::name,
(oldName, newName) -> newName
));
Здесь при совпадении ключей останется новое значение.
Можно сделать наоборот:
(oldName, newName) -> oldName
Тогда сохранится первое значение.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍5🔥4
Примитивные типы хранят значение напрямую в переменной и работают без объектов. Ссылочные типы хранят ссылку на объект, при этом сам объект размещается в heap, а переменная указывает на него.
Также показано различие поведения при копировании: значение копируется целиком для примитивов и копируется ссылка для объектов.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍6❤5
Ищем самый дорогой товар через Stream API!
Допустим, есть список товаров, и нужно найти позицию с максимальной ценой.
Создадим простую модель:
Подготовим данные:
Можно пройтись циклом и вручную хранить текущий максимум:
Но через Stream API это можно сделать короче:
А
Поэтому результат лучше обработать явно:
Такой подход удобно использовать для товаров, заказов, рейтингов, зарплат, статистики и любых списков, где нужно найти максимальный объект по конкретному полю.
👉 Java Ready | #практика
Допустим, есть список товаров, и нужно найти позицию с максимальной ценой.
Создадим простую модель:
record Product(String name, BigDecimal price) {}Подготовим данные:
List<Product> products = List.of(
new Product("Keyboard", new BigDecimal("79.99")),
new Product("Mouse", new BigDecimal("39.99")),
new Product("Monitor", new BigDecimal("249.99"))
);
Можно пройтись циклом и вручную хранить текущий максимум:
Product top = products.get(0);
for (Product product : products) {
if (product.price().compareTo(top.price()) > 0) {
top = product;
}
}
Но через Stream API это можно сделать короче:
Optional<Product> top = products.stream()
.max(Comparator.comparing(Product::price));
Comparator.comparing(Product::price) говорит Java сравнивать товары по цене.А
max() возвращает Optional, потому что список может быть пустым.Поэтому результат лучше обработать явно:
Product product = top.orElseThrow();
Такой подход удобно использовать для товаров, заказов, рейтингов, зарплат, статистики и любых списков, где нужно найти максимальный объект по конкретному полю.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3🔥3
В задаче нужно определить, закрыты ли все скобки. Порядок вложенности не проверяется, только равенство количества.
Сегодня в посте:
• Зададим строку;
• Посчитаем количество для каждого вида скобок;
• Проверим, что все счётчики равны нулю.
Такой способ подходит для простых проверок строк, где важен сам факт закрытия скобок, а не порядок.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍3❤2🤝1
Почему Collections.unmodifiableList() не всегда делает список неизменяемым?
На первый взгляд такой код надёжно защищает коллекцию:
Через languages действительно нельзя вызвать add() или remove(): Java выбросит UnsupportedOperationException.
Но unmodifiableList() не создаёт отдельную коллекцию. Он возвращает только неизменяемое представление исходного списка.
Поэтому изменение source будет видно и через languages. В примере программа выведет:
Если нужна независимая неизменяемая копия, лучше использовать List.copyOf():
Теперь последующие изменения source не затронут languages. Это особенно важно, когда список сохраняется в поле объекта или возвращается из публичного API.
Стоит учитывать ещё одну деталь: List.copyOf() не допускает null-элементы и сразу выбросит NullPointerException, если они есть в исходной коллекции.
👉 Java Ready | #совет
На первый взгляд такой код надёжно защищает коллекцию:
var source = new ArrayList<>(List.of("Java", "C++"));
var languages = Collections.unmodifiableList(source);
source.add("C#");
System.out.println(languages);Через languages действительно нельзя вызвать add() или remove(): Java выбросит UnsupportedOperationException.
Но unmodifiableList() не создаёт отдельную коллекцию. Он возвращает только неизменяемое представление исходного списка.
Поэтому изменение source будет видно и через languages. В примере программа выведет:
[Java, C++, C#]
Если нужна независимая неизменяемая копия, лучше использовать List.copyOf():
var languages = List.copyOf(source);
Теперь последующие изменения source не затронут languages. Это особенно важно, когда список сохраняется в поле объекта или возвращается из публичного API.
Стоит учитывать ещё одну деталь: List.copyOf() не допускает null-элементы и сразу выбросит NullPointerException, если они есть в исходной коллекции.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍5🔥3
Например,
HashMap позволяет получать данные по ключу, а ArrayList обеспечивает удобную работу с динамическими списками и доступом по индексу.На картинке — основные коллекции: List, Set, Queue, Map, их реализации (
ArrayList, HashSet, TreeMap, HashMap и другие), особенности хранения данных, поддержка дубликатов, порядок элементов, основные методы и оценка сложности операций.Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10🔥7👍6
Разработчики из Anthropic обновили и структурировали масштабный хаб готовых запросов для своей языковой модели. База создана для того, чтобы пользователи могли выжать максимум из Claude при решении прикладных и технических задач, не тратя время на самостоятельный подбор формулировок.
🟦 Для безопасности: готовые конструкции для проверки кода на уязвимости и анализа граничных условий работы алгоритмов.
🟦 Для разработчиков: шаблоны для глубокого ревью кода, автоматического поиска багов, рефакторинга, написания юнит-тестов и проектирования архитектуры.
🟦 Для автоматизации и менеджмента: промпты под стратегическое планирование, парсинг неструктурированных данных, генерацию технической документации и выстраивание логики для ИИ-агентов.
Каждый шаблон снабжен подробным разбором: авторы пошагово объясняют, почему выбрана именно такая структура запроса, как модель интерпретирует переменные и как правильно передавать контекст. Поскольку библиотека официальная, все промпты оптимизированы под особенности контекстного окна и логику мышления последних моделей семейства Claude.
Нейросети отлично автоматизируют рутину и помогают искать уязвимости, но управлять ими может только тот, кто понимает саму базу и суть киберугроз.
Если вы хотите заложить мощный фундамент начните с нашего бесплатного курса (его прошли уже 1108 человек!).
🟦 Разберетесь, как работают кибератаки и как грамотно защитить свои данные.
🟦 Познакомитесь с направлениями и профессиями в кибербезопасности, чтобы выбрать свой трек.
🟦 Получите скидку, если решите продолжить обучение в CyberYozh Academy.
👉 Начните бесплатно прямо сейчас
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1😁1
Генерируем безопасный URL-токен на Java!
Для ссылки подтверждения, сброса пароля или временного приглашения нужен непредсказуемый токен. Обычный Random для этого не подходит, поэтому используем SecureRandom.
Создадим генератор случайных байтов:
Теперь напишем метод генерации:
URL Encoder не использует символы, которые могут сломать адрес. Дополнительное кодирование результата не требуется.
Создадим токен из 32 случайных байтов:
Пример результата:
Теперь его можно добавить в ссылку:
На сервере безопаснее хранить хеш токена:
Также у токена должен быть срок действия и возможность только одноразового использования.
👉 Java Ready | #практика
Для ссылки подтверждения, сброса пароля или временного приглашения нужен непредсказуемый токен. Обычный Random для этого не подходит, поэтому используем SecureRandom.
Создадим генератор случайных байтов:
private static final SecureRandom RANDOM =
new SecureRandom();
Теперь напишем метод генерации:
static String generateToken(int size) {
byte[] data = new byte[size];
RANDOM.nextBytes(data);
return Base64.getUrlEncoder()
.withoutPadding()
.encodeToString(data);
}URL Encoder не использует символы, которые могут сломать адрес. Дополнительное кодирование результата не требуется.
Создадим токен из 32 случайных байтов:
String token = generateToken(32);
System.out.println(token);
Пример результата:
Pp1HgxVmySpQJQi3KUUPN5ZXqCV4-ZPvP12Ft49XiI0
Теперь его можно добавить в ссылку:
String link =
"https://ready.com/confirm?token=" + token;
На сервере безопаснее хранить хеш токена:
var digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(
token.getBytes(StandardCharsets.UTF_8)
);Также у токена должен быть срок действия и возможность только одноразового использования.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10❤5👍4
This media is not supported in your browser
VIEW IN TELEGRAM
На странице собрана коллекция шпаргалок и полезных ресурсов для Java-разработчиков. Здесь есть материалы по Java Core, JPA и Hibernate, Stream API, Lombok, коллекциям, библиотекам для работы с JSON, а также ссылки на обучающие материалы, популярные open-source проекты и подборки для подготовки к собеседованиям.
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝8❤4👍2
Создаём погодного Telegram-бота на Java!
В этой статье:
• Как подключить OpenWeatherMap и получать актуальную погоду
• Как обновлять прогноз через inline-кнопку без новых сообщений
• Как настроить FSM-диалог, валидацию времени и рассылку по расписанию
👉 Java Ready | #статья
В этой статье:
• Как подключить OpenWeatherMap и получать актуальную погоду
• Как обновлять прогноз через inline-кнопку без новых сообщений
• Как настроить FSM-диалог, валидацию времени и рассылку по расписанию
Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3🔥3👍2
Собирайте значения по ключу через computeIfAbsent()!
Когда в
Здесь приходится отдельно получать значение, создавать список и записывать его обратно в
Функция создания вызывается только тогда, когда ключ отсутствует или связан с
В результате оба значения окажутся в одном списке:
Тот же приём подходит для группировки объектов, ленивого создания настроек и простых локальных кэшей:
Важно: если функция вернёт
👉 Java Ready | #совет
Когда в
Map нужно хранить несколько значений для одного ключа, часто появляется ручная проверка:var values = tags.get(topic);
if (values == null) {
values = new ArrayList<>();
tags.put(topic, values);
}
values.add(tag);
Здесь приходится отдельно получать значение, создавать список и записывать его обратно в
Map.computeIfAbsent() объединяет эти действия:tags.computeIfAbsent(topic, key -> new ArrayList<>())
.add(tag);
Функция создания вызывается только тогда, когда ключ отсутствует или связан с
null. Если список уже существует, Java сразу вернёт его:tags.computeIfAbsent("java", key -> new ArrayList<>())
.add("collections");
tags.computeIfAbsent("java", key -> new ArrayList<>())
.add("streams");В результате оба значения окажутся в одном списке:
{java=[collections, streams]}Тот же приём подходит для группировки объектов, ленивого создания настроек и простых локальных кэшей:
var config = configs.computeIfAbsent(
serviceName,
this::loadConfig
);
Важно: если функция вернёт
null, новое соответствие в Map добавлено не будет.Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍3🔥2
Интересная статья о том, как создавались 2D-игры для кнопочных Java-телефонов!
В этой статье:
• Как J2ME и MIDP использовались для разработки мобильных игр
• Как работали спрайты, игровой цикл, ввод и мобильная графика
• Почему разные разрешения, объём памяти и коды кнопок мешали переносимости игр
👉 Java Ready | #статья
В этой статье:
• Как J2ME и MIDP использовались для разработки мобильных игр
• Как работали спрайты, игровой цикл, ввод и мобильная графика
• Почему разные разрешения, объём памяти и коды кнопок мешали переносимости игр
Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍3🔥3
Почему split(".") не разделяет строку по точке?
На первый взгляд такой код выглядит правильно:
Но split() принимает не обычную строку-разделитель, а регулярное выражение.
В regex точка означает любой символ. Поэтому выражение "." совпадает практически со всей строкой, а пустые элементы в конце результата split() удаляет.
В результате можно неожиданно получить пустой массив:
Чтобы искать именно точку, её нужно экранировать:
Два обратных слеша нужны из-за двойной обработки: сначала Java превращает \\ в один слеш, а затем regex получает выражение \.
Если разделитель приходит из переменной, безопаснее не экранировать его вручную:
Pattern.quote() превращает строку в литеральное регулярное выражение. Это особенно полезно для разделителей вроде точки, вертикальной черты, плюса или скобок.
👉 Java Ready | #совет
На первый взгляд такой код выглядит правильно:
String[] parts =
"api.example.com".split(".");
Но split() принимает не обычную строку-разделитель, а регулярное выражение.
В regex точка означает любой символ. Поэтому выражение "." совпадает практически со всей строкой, а пустые элементы в конце результата split() удаляет.
В результате можно неожиданно получить пустой массив:
System.out.println(
Arrays.toString("a.b".split("."))
);
// []
Чтобы искать именно точку, её нужно экранировать:
String[] parts =
"api.example.com".split("\\.");
System.out.println(
Arrays.toString(parts)
);
// [api, example, com]
Два обратных слеша нужны из-за двойной обработки: сначала Java превращает \\ в один слеш, а затем regex получает выражение \.
Если разделитель приходит из переменной, безопаснее не экранировать его вручную:
String separator = ".";
String regex =
Pattern.quote(separator);
String[] parts = text.split(regex);
Pattern.quote() превращает строку в литеральное регулярное выражение. Это особенно полезно для разделителей вроде точки, вертикальной черты, плюса или скобок.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍4🔥2