Секреты Java
الذهاب إلى القناة على Telegram
Обсуждаем Java, архитектуру, фреймворки и всё, о чем должны говорить разработчики. Владелец: @Alexey_Morl Реклама на бирже: https://telega.in/c/java_secrets
إظهار المزيد7 991
المشتركون
لا توجد بيانات24 ساعات
لا توجد بيانات7 أيام
لا توجد بيانات30 أيام
أرشيف المشاركات
7 991
Коллеги, всем привет!
Много людей в комментариях и личку давно просили больше тестов и наконец у меня дошли руки, чтобы сделать отдельный канал, в котором я буду ежедневно публиковать тесты по Java Core, а также Spring.
Тесты, которые там публикую можно спокойно использовать в том числе для подготовки к сертификации по:
▫️OCA/OCP экзаменам от Oracle
▫️Сертификации по Spring от VMWare.
Или просто когда скучно на перерыве за кофе)
Подключайтесь 👉 https://t.me/+sXlgDvVTR8Q0ZGYy
7 991
✅ Лямбда-выражения и Stream API – это мощные инструменты, появившиеся в Java 8, которые значительно упрощают работу с коллекциями и делают код более выразительным и функциональным.
Лямбда-выражения:
Лямбда-выражение – это анонимная функция, которая может быть передана как аргумент методу. Они позволяют писать более компактный и читаемый код используя функциональные интерфейсы (интерфейсы с одним абстрактным методом).
Конструкция:
(параметры) -> { тело }
Пример:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));
В этом примере мы используем лямбда-выражение name -> System.out.println(name) для вывода каждого элемента списка в консоль.
Stream API:
Stream API предоставляет удобный способ обработки коллекций данных. Stream – это последовательность элементов, которая может быть создана из различных источников. Это могут быть коллекции, списки, наборы, массивы, строки, файлы или даже генераторы чисел. Все эти источники могут быть легко преобразованы в потоки для последующей обработки.
Со Stream-ом можно выполнять два типа операций: промежуточные (intermediate) и терминальные (terminal)
Промежуточные операции:
Промежуточные операции возвращают новый поток, трансформируя исходный. Они могут быть цепочкой друг за другом.
- filter(Predicate predicate): Фильтрует элементы, оставляя только те, которые удовлетворяют предикату.
- map(Function mapper): Преобразует каждый элемент в новый элемент, используя функцию преобразования.
- flatMap(Function mapper): Преобразует каждый элемент в поток и объединяет все полученные потоки в один.
- distinct(): Удаляет дубликаты из потока.
- sorted(): Сортирует элементы потока по естественному порядку или по заданному компаратору.
- limit(long maxSize): Ограничивает количество элементов в потоке.
- skip(long n): Пропускает первые n элементов в потоке.
- peek(Consumer action): Выполняет действие для каждого элемента потока, но не изменяет сам поток.
Терминальные операции:
Терминальные операции завершают обработку потока и возвращают результат определенного типа.
- forEach(Consumer action): Выполняет действие для каждого элемента потока.
- anyMatch(Predicate predicate): Проверяет, существует ли хотя бы один элемент, удовлетворяющий предикату.
- allMatch(Predicate predicate): Проверяет, все ли элементы удовлетворяют предикату.
- noneMatch(Predicate predicate): Проверяет, нет ли ни одного элемента, удовлетворяющего предикату.
- findFirst(): Возвращает первый элемент потока или Optional.empty(), если поток пуст.
- findAny(): Возвращает любой элемент потока или Optional.empty(), если поток пуст.
- reduce(T identity, BinaryOperator accumulator): Выполняет последовательное применение бинарной операции к элементам потока, начиная с начального значения.
- collect(Collector collector): Складывает элементы потока в коллекцию или другую структуру данных, используя коллектор.
Пример:
Создать поток можно по разному:
- Stream.of(elements) – создает поток из массива элементов.
- List.stream() – создает поток из списка.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.reduce(0, Integer::sum);
System.out.println(sum); // Вывод: 20
Если кому-то сложно прочитать, что происходит в примере:
1. Фильтруем числа, которые делятся на 2.
2. Возводим каждый элемент в квадрат.
3. Складываем все полученные числа.
В целом если подытожить и посмотреть на преимущества:
- Функциональный стиль: Позволяет писать более выразительный и лаконичный код гораздо меньшего объема.
- Легкость в чтении: Операции над потоками зачастую легко читаются и понимаются(но не всегда, да-да).
- Stream-ы уменьшают побочный эффект: методы Stream API не меняют исходные коллекции.
И кстати, чуть не забыл, Stream API поддерживает параллельную обработку данных)
🫡 Секреты Java
#stream #лямбда7 991
📝 Хабр теперь в Telegram!
Здесь публикуют лучшие статьи для программистов со всех направлений — заходи, читай, изучай:
Статьи для Python разработки
Статьи для Frontend разработки
Статьи для Java разработки
Статьи для C/C++ разработки
Статьи для C# разработки
Статьи для Android разработки
Статьи для iOS разработки
Статьи для безопасников
Статьи для разработчиков игр
Статьи для тестировщиков
Статьи для DevOps-инженеров
🔗 Ссылки скоро сгорят, успей подать заявку
7 991
✅ Что такое раннее (Early Binding) и позднее связывание (Late Binding)?
Связывание - это привязка вызова метода к конкретному коду. Java поддерживает два вида связывания: раннее и позднее.
▫️Раннее (статическое) связывание происходит во время компиляции. Проще говоря, компилятор заранее знает какой именно метод будет вызван. Такой механизм связывания используется для статических, private или final методов.
▫️Позднее (динамическое) связывание происходит во время выполнение программы. Это позволяет динамически определять, какой метод будет вызван в зависимости от объекта, на который ссылается ссылка. Это, как правило, связано с переопределением методов в наследуемых классах.
Зная основные различия видов связываний, не сложно догадаться, что раннее связывание обеспечивает быстрый поиск нужного кода для выполнение, а позднее - добавляет гибкости языку программирования и позволяет реализовывать полиморфизм.
🫡 Секреты Java
#java
7 991
Стейт-машины: The Good, The Bad, The Ugly
Даша Андреева, тимлид команды Биллинга в Яндекс 360 рассказывает, как они с командой решили проблему реализации стейт-машин с помощью spring-state-machine. В докладе — примеры и антипримеры того, когда такой паттерн не нужно применять вовсе.
Будет интересно всем, кто когда-либо сталкивался с проектированием систем, основанных на состояниях.
Смотреть доклад на Youtube
Смотреть доклад в ВК
7 991
✅Настройка JVM
Ранее я писал про настройку выделения памяти, но какие еще существую параметры для JVM?
Основные параметры JVM, которые могут вам пригодиться:
▫️
-Xms и -Xmx. Про них можете почитать в этом посте.
▫️ -XX:+UseG1GC. Одним из ключевых факторов стабильности приложения является правильно выбрал алгоритм сборки мусора. Для JVM можно указать следующие параметров для выбора Garbage collector:-XX:+UseSerialGC, -XX:+UseParallelGC, -XX:+USeParNewGC, -XX:+UseG1GC
▫️-XX:+HeapDumpOnOutOfMemoryError. При возникновении OutOfMemoryError JVM создавать дамп кучи, что позволит его проанализировать для выявления причин возникновении ошибки.
▫️-XX:MaxMetaspaceSize. С версии Java 8 размер метапространства не определен и автоматически увеличивается при загрузки новых классов
Зачем нужно использовать параметры JVM?
Параметры JVM позволяют вам настраивать поведение виртуальной машины, что может значительно повлиять на производительность, использование памяти и стабильность приложения. Правильная настройка может помочь избежать проблем с производительностью и утечками памяти.
Настройка JVM - это всегда выбор между производительностью и стабильностью. При указании параметров JVM не поленитесь протестировать как ваше приложение будет работать с разными конфигурациями, так вы сможете найти оптимальные значения.
🫡 Секреты Java
#java #jvm7 991
Расширьте свои навыки в программировании с бесплатным мини-курсом по Java! Научитесь создавать Telegram-ботов, разрабатывать программы для обработки данных и строить чаты на фреймворке Spring. Не упустите шанс — начните обучение уже сегодня: 👉https://epic.st/p_nYgy?erid=2Vtzqvzih9o
Формат мини-курса отлично подойдёт для обучения из любой точки мира: смотрите видео в удобное время и закрепляйте навыки на практике.
🎁 За время обучения вы получите 5 полезных материалов в подарок, сертификат на скидку 10 000 рублей на любой курс, персональную карьерную консультацию и доступ к изучению английского языка в Skillbox на год.
До встречи на мини-курсе. Старт после регистрации!
Реклама. ЧОУ ДПО «Образовательные технологии «Скилбокс (Коробка навыков)», ИНН: 9704088880
7 991
✅ Dockerfile
Как говорилось в прошлом посте про Docker, Dockerfile - это текстовый файл, который содержит команды для сборки образа Docker. Этот файл определяет, как именно будет выглядеть контейнер, включая операционную систему, зависимости, настройки и команды, которые нужно выполнить.
Вот список основных инструкций, которые могут быть применены при написании dockerfile:
▫️FROM - указывает родительский образ
▫️RUN - выполняет команды в контейнере на этапе сборки
▫️COPY - копирование файлов проекта
▫️ADD - копирует файлы по ссылке и распаковываете архивы
▫️CMD - указывает команду, которая будет выполняться при запуске контейнера
▫️ENV - задает переменные среды окружения внутри контейнера
▫️WORKDIR - задаёт рабочую папку проекта
▫️EXPOSE - открывает порты, с помощью которых можно будет взаимодействовать с приложением
Напишем простой dockerfile для приложения, в котором есть только один REST контроллер:
FROM gradle:7.6.0-jdk17
WORKDIR /app
COPY . .
RUN gradle build --no-daemon
EXPOSE 8080
CMD ["java", "-jar", "/app/build/libs/demo-0.0.1-SNAPSHOT.jar"]
1) В качестве основы использует образ, который содержит Gradle с JDK 17
2) Создаем рабочую директорию
3) Копируем все файлы (файлы для gradle и исходный код)
4) Собираем приложение
5) Открываем порт для приложения
6) Указываем команду для запуска нашего приложения
Осталось выполнить пару команд в консоли, чтобы собрать наш образ и запустить на его основе контейнер:
docker build -t demo .
docker run -p 8080:8080 demo
Аргументы первой команды:
▫️-t demo - название образа
▫️. - путь по которому Docker будет искать Dockerfile. Точка = текущая директория
Аргументы второй команды:
▫️-p 8080:8080 - связываем порт 8080 контейнера с портом 8080 на хосте
▫️demo - название Docker образа, на основе которого будет запускаться контейнер
Выполнив команду docker images можем увидеть наш образ:
REPOSITORY TAG CREATED SIZE
demo latest 9 seconds ago 889MB
Убедимся, что контейнер запущен, выполнив docker ps в командной строке:
CONTAINER ID IMAGE STATUS PORTS
e343769f7330 demo 15 seconds ago 0.0.0.0:8080->8080/tcp
Если контейнер успешно запущен, то вы должны увидеть подобный результат.
Поздравляю, теперь вы научились запускать свое приложение в Docker.
Если вас тоже смущает тяжелый docker образ (889MB) для небольшого демо приложения, то подготовлю для вас пост про оптимизацию dockerfile)
🫡 Секреты Java
#docker #dockerfile7 991
🚨 Не знаешь как подготовиться к собесу по Java? Хватит гадать, бери готовые ответы!
Очень часто на интервью по Java задают одни и те же вопросы по базовым темам, вне зависимости от копании и грейда!
Хотим порекомендовать новый материал от Павла Сорокина, в котором он агрегировал свой опыт прохождения собеседований и менторства и подробно разобрал самые частые вопросы по Java Core и многопоточности в одном видео-гайде.
🔥 Что внутри гайда?
📍Обзор самых популярных вопросов на собеседованиях по Java Core и многопоточности.
📍Пошаговые объяснения и лайфхаки, как правильно отвечать.
📍Запись успешного собеса на Junior в один из крупнейших российских финтехов.
Благодаря этому гайду ученики Паши легко проходят собеседования и получают офферы на 150-350 тысяч в крупнейшие компании. Теперь твоя очередь! Делимся видео-гайдом совершенно бесплатно 🎁
🚀 Переходи в бота, забирай гайд и будь готов к любому повороту на собесе!👇🏻
https://t.me/JavaLearnBot?start=c1724626210163-38-ds
7 991
✅ Локальные и анонимные классы
В продолжение поста про вложенные классы в этом поговорим про локальные и анонимные классы.
▫️Локальный класс
Это особая разновидность внутренних классов. Локальный класс можно определить внутри любого блока кода, он тесно связан с областью видимости, в которой он определен. В целом по свойствам он похож на нестатический вложенный класс, но с некоторыми особенностями:
- Метод создания не может быть статическим (нужен экземпляр внешнего класса).
- Желательно использовать final переменные метода.
- Класс нельзя объявлять с модификатором доступа.
В работе можно вообще не встретить его использования, но пример рассмотрим:
public class LocalClassExample {
public Comparator getMyComparator() {
class MyComparator implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1; // Сортировка по убыванию
}
}
return new MyComparator();
}
}
public static void main(String[] args) {
int[] arr;// массив каких-то важных несортированных чисел
Arrays.sort(arr, new LocalClassExample().getMyComparator())
}
В общем "очень интересно", идём дальше)
▫️Анонимный класс
Анонимный класс в Java — это класс, который не имеет явного имени. Он определяется прямо там, где используется, обычно для реализации интерфейса или расширения класса. Это позволяет создавать одноразовые объекты, которые нужны только в конкретном месте кода.
java
List<Integer> numbers = Arrays.asList(3, 1, 4);
numbers.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1; // Сортировка по убыванию
}
});
Анонимные классы были важным инструментом в Java до появления лямбда-выражений. Хотя лямбда-выражения предлагают более лаконичный и функциональный синтаксис, анонимные классы все еще могут быть полезны в некоторых в более сложных случаев, когда нужно определить дополнительные поля или методы, или когда требуется совместимость с более старыми версиями Java.
Коль уж сказали про лямбды - приведем пример переписав предыдущий короче:
List<Integer> numbers = Arrays.asList(3, 1, 4); numbers.sort((o1, o2) -> o2 - o1);
Так конечно намного короче, но про лямбда-выражения и Stream-ы мы поговорим в скором будущем.
🫡 Секреты Java
#анонимныйкласс #лямбда7 991
erid: LjN8KZFH8
Станьте разработчиком нейро-сотрудников на Python и зарабатывайте от 150.000₽ в месяц 🔥🔥🔥
Мы научим вас создавать топовых нейро-сотрудников на базе GPT-4 Omni, и вы сможете:
1️⃣ Устроиться разработчиком в крупную компанию и зарабатывать от 150 тыс. ₽ в меc.
2️⃣ Разрабатывать такие проекты на заказ и зарабатывать от 500 тыс. ₽ за проект
3️⃣ Создать нейро-сотрудника в вашей компании и вырасти на +30-100% в зарплате
Что будет на интенсиве?
🧬 Короткая теория: как создаются нейро-сотрудники с GPT-4o на Python
🧬 Практика: мы создадим нейро-консультанта, нейро-HR, нейро-маркетолога и др.
Ведущий — Senior AI разработчик и основатель Университета искусственного интеллекта
🔥 Регистрируйтесь на бесплатный интенсив! Встречаемся в ближайший четверг!
7 991
✅ StringBuilder
Все мы знаем, что объекты типа String являются immutable (неизменяемыми) и каждое их изменение влечет добавление новой строки в String pool. А, что если в вашей программе строки часто изменяются? Это приведет к расходованию памяти, а этот ресурс не бесконечный. В таком случае лучше использовать
StringBuilder .
StringBuilder - это класс из пакета java.lang, который предоставляет возможность работы с изменяемыми строками. Вместо обычных строк StringBuilder под капотом использует массив, размер(capacity) которого по умолчанию равен 16.
Существует несколько способов объявить переменную типа StringBuilder:
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder("Java");
StringBuilder sb3 = new StringBuilder(sb2);
StringBuilder sb4 = new StringBuilder(20);
▫️Использовать пустой конструктор - capacity = 16
▫️Передать в конструктор сроку - capacity = длина строки + 16
▫️Передать в конструктор любой класс, который реализует интерфейс CharSequence - capacity = длина CharSequence + 16
▫️Указать нужный capacity при создании переменной
Модификация значений происходит с помощью встроенных методов:
▫️append("str") - добавление строки в конец
▫️insert(index, "str") - добавление строки в определенную позицию
▫️sb.delete(start, end) - удаление подстроки
Вот пример их использования:
sb.append("Hello");
sb.insert(5, " World");
sb.delete(6, 11);
Важная особенность StringBuilder заключается в том, что его нельзя использовать в многопоточной среде, но для этой цели существует StringBuffer, который предоставляет такой же функционал, но скорость его работы, естественно, ниже.
🫡 Секреты Java
#java #string #stringbuilder7 991
Разыскиваются 5 активных JAVA разработчиков 🔥🔥🔥
Для обучения AI-разработке!
Мы научим вас создавать и тренировать нейронные сети, и вы сможете:
1️⃣ Устроиться разработчиком в крупную компанию и зарабатывать от 150 тысяч руб. в месяц
2️⃣ Разрабатывать такие проекты на заказ и зарабатывать от 500 тысяч руб. за проект
3️⃣ Создать нейро-сотрудника в вашей компании и вырасти на +30-100% в зарплате
На интенсиве будет много практики: создадим 9 нейросетей за 1 вечер:
🧬 Оценка выброса CO2 по параметрам машины
🧬 Сегментация изображения для робота доставщика
🧬 Трекинг людей на видео
🧬 Распознавание речии другие
Ведущий интенсива - Senior AI-разработчик нейросетей и основатель Университета искусственного интеллекта
🔥 Регистрируйтесь на бесплатный интенсив! Встречаемся в ближайшую среду. Вы узнаете, как освоить самую востребованную профессию 2024 года!
Реклама. ООО "ТЕРРА ЭЙАЙ". ИНН 9728019395.
7 991
✅ Решение или проблема?
В Java существует несколько способов создания и инициализации объектов в одном выражении. Один из таких способов - это double brace initialization.
Чаще всего инициализация с использованием двойных фигурных скобок используется при создании коллекций.
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
Данные код можно привести к следующему виду:
Set<Integer> set = new HashSet<>() {{
add(1);
add(2);
add(3);
}};
Казалось бы так код выглядит лаконичнее, но у такого подхода есть проблема.
Каждый раз при использовании такой инициализации создается анонимный класс, который имеет неявную ссылку на внешний класс, что может привести к утечкам памяти.
Именно поэтому Double brace initialization - антишаблон.
Если у вас осталось желание инициализировать коллекции при их создании, то рассмотрите фабричные методы коллекций (не забудьте что тогда они будут unmodifiable), либо можете использовать Stream API.
🫡 Секреты Java
#java