Java | Фишки и трюки
7.21K subscribers
182 photos
29 videos
6 files
40 links
Java: примеры кода, интересные фишки и полезные трюки

Купить рекламу: https://telega.in/c/java_tips_and_tricks

✍️По всем вопросам: @Pascal4eg
Download Telegram
😁43👨‍💻3❤‍🔥1👍1👏1
🔄 stream().map().filter().collect() — читаемо и мощно

Java Stream API — это как grep | awk | sort в Linux, только в Java-стиле.
Самая частая связка: map → filter → collect. И она может заменить кучу шаблонного кода.

Допустим, у нас есть список:


List<String> names = List.of("Alice", "bob", "CHARLIE", "dave");


👉 Хочешь получить отфильтрованные, приведённые к верхнему регистру имена, которые длиннее 3 символов?

До Stream API:


List<String> result = new ArrayList<>();
for (String name : names) {
String upper = name.toUpperCase();
if (upper.length() > 3) {
result.add(upper);
}
}


С stream():

List<String> result = names.stream()
.map(String::toUpperCase)
.filter(s -> s.length() > 3)
.collect(Collectors.toList());


➡️ Читаемо, как SQL: "преобразуй → отфильтруй → собери".


✔️ Разберём подробнее:

1. `map()` — преобразование
   .map(String::trim)
.map(String::toLowerCase)


🔄 Применяет функцию ко всем элементам. Тип может измениться.

2. `filter()` — отбор
   .filter(s -> s.startsWith("a"))


Оставляет только те элементы, которые удовлетворяют условию.

3. `collect()` — сборка результата
   .collect(Collectors.toSet())
.collect(Collectors.joining(", "))


🧺 Собирает результат обратно в список, множество, строку и т.д.

📌 Реальный пример — фильтруем активных пользователей по возрасту:

List<User> users = getUsers();

List<String> activeAdults = users.stream()
.filter(User::isActive)
.filter(u -> u.getAge() >= 18)
.map(User::getName)
.collect(Collectors.toList());


➡️ Без лишних if, for и add() — код фокусируется на логике, а не на реализации.

🗣 Запомни: Цепочка map().filter().collect() — это про читаемый и декларативный код.
Не пиши как императивный робот, пиши как человек: что ты хочешь получить — а не как это сделать.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍153🔥2👨‍💻1
☕️ final в Java — стоп-сигнал для изменений

В Java final — это как «не трогай»: запрет на изменение.
Но что именно он запрещает? Всё зависит от того, где его поставить: переменная, метод, класс.

Разберёмся 👇

1. 📦 final переменные — нельзя переназначить

final int port = 8080;
port = 9090; // ошибка компиляции


➡️ Значение фиксируется один раз. Для примитивов — это само значение, для объектов — это ссылка.

final List<String> list = new ArrayList<>();
list.add("Hello"); // можно
list = new ArrayList<>(); // нельзя


🧠 Важно: final не делает объект неизменяемым. Только ссылку.

2. 🔒 final методы — нельзя переопределить в наследниках

class Animal {
final void sleep() {
System.out.println("Zzz...");
}
}

class Dog extends Animal {
// Нельзя переопределить sleep()
}


➡️ Полезно, если хочешь защитить логику метода от изменений в подклассах.

3. 🧱 final классы — нельзя наследовать вообще

final class Utility {
static void log(String msg) { ... }
}


class MyUtil extends Utility {} //  ошибка


➡️ Применяют для:

🟢 утилитарных классов (Math, String)
🟢 защиты от подмены логики (SecurityManager, System)

🎯 Частые применения в дикой природе:

🟢 final аргументы в методах → защищает от случайного переназначения
🟢 final поля + @Immutable → хорошая практика для DTO
🟢final классы → в record, enum, String, LocalDate и т.д.


🗣 Запомни:final = контроль. Это способ сказать «вот это трогать нельзя». Используй его осознанно — чтобы сделать поведение предсказуемым и безопасным.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥3👨‍💻21
☕️Text Blocks в Java: читаемые строки без \n и слёз

До Java 13 работа с многострочными строками была болью. JSON? HTML? SQL? Только через "\n" + и кучу экранирования.
Но с Text Blocks всё стало проще, понятнее и читаемо.

Сравни:

До:
String html = "<html>\n" +
" <body>Hello</body>\n" +
"</html>";


После (Text Block):

String html = """
<html>
<body>Hello</body>
</html>
""";


➡️ Стало чище, короче и как в оригинале. Это обычная String, просто оформленная красиво.

✔️ Преимущества Text Blocks:

1. 👍 Читаемость на уровне "как есть"
Код больше не превращается в кашу. Особенно полезно для:

SQL-запросов:
     String query = """
SELECT id, name
FROM users
WHERE active = true
ORDER BY created_at DESC
""";


HTML/JSON шаблонов:

     String json = """
{
"name": "Alice",
"role": "admin"
}
""";


2. 👍 Меньше экранирования
Забудь про \", \\n, \\t — теперь можно писать почти как в блокноте.

3. 👍 Автоматическое выравнивание
Java сама уберёт начальные отступы на основе самой "узкой" строки.

Пример:
   String msg = """
Line 1
Line 2
Line 3
""";


➡️ Результат будет:
Line 1
Line 2
Line 3


4. 👍 Интеграция с .formatted()
Нельзя вставить переменные прямо в Text Block?
Используем .formatted() — коротко и читабельно:
String user = "Bob";
String template = """
{
"user": "%s",
"access": "granted"
}
""".formatted(user);
````
```java
String s = """
Hello""";
System.out.println(s.length()); // 6, а не 5 (есть \n)


3. 🟢 Нет интерполяции переменных
Нельзя писать так:
   String name = "Eve";
String wrong = """
Hello, $name!
"""; // не сработает


Вместо этого:
   String right = """
Hello, %s!
""".formatted(name);


🗣️ Запомни: Text Blocks делают строки в Java человечными. Это не просто сахар — это инструмент, чтобы твой код говорил с тобой на одном языке. Используй их для всего, что требует форматирования — и забудь про + "\n".
Please open Telegram to view this post
VIEW IN TELEGRAM
18👍4👨‍💻2🔥1
🏭 Factory в Java: просто, без бойлерплейта

Factory-паттерн — это способ создавать объекты, не раскрывая логику создания. Но в Java он часто обрастает шаблонами, абстракциями и XML'ем. Зачем? Можно проще.

Допустим, у нас есть интерфейс:

interface Notification {
void send(String message);
}


И реализации:

class EmailNotification implements Notification {
public void send(String message) {
System.out.println("Email: " + message);
}
}

class SmsNotification implements Notification {
public void send(String message) {
System.out.println("SMS: " + message);
}
}


➡️ А теперь сама Factory — без лишнего:

class NotificationFactory {
public static Notification create(String type) {
return switch (type) {
case "email" -> new EmailNotification();
case "sms" -> new SmsNotification();
default -> throw new IllegalArgumentException("Unknown type");
};
}
}


Использование:

Notification n = NotificationFactory.create("email");
n.send("Hello world!");


✔️ Что получили:

1. 👍 Централизованное создание объектов
Меняем реализацию в одном месте.

2. 👍 Гибкость без наследования
Можно возвращать любые классы — хоть анонимные, хоть лямбды.

3. 👍 Без бойлерплейта
Никаких XML, DI-фреймворков и пяти уровней абстракции.


⚠️ Но не переусердствуй:

1. 🟢 Не делай фабрику ради фабрики
Если new работает — не трогай.

2. 🟢 Не забывай про enum
Часто enum c фабрикой — читается лучше, чем строки.

🗣️ Запомни: Factory — это не про паттерны ради паттернов. Это про чистый код и простую подмену реализаций. Не усложняй — Java и так может быть элегантной.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍194🔥3
🚀 Кеширование с @Cacheable — быстро и просто в Spring

Когда метод тяжёлый (долго считает, лезет в БД или API) — зачем вызывать его 100 раз, если результат тот же?
Решение: кеш. В Spring это делается одной аннотацией.

Что делает @Cacheable?

Она сохраняет результат метода в кеш.
При повторном вызове с теми же аргументами — возвращает значение из кеша, не запуская метод снова.

@Cacheable("users")
public User getUserById(Long id) {
System.out.println("Fetching from DB...");
return userRepository.findById(id).orElseThrow();
}


Первый вызов: метод выполнится → результат кешируется.
Следующие вызовы с тем же id: результат берётся из кеша.

⚙️ Как включить кеш?

1. Добавь зависимость (если ещё нет):

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>


2. Включи кеш в @Configuration:

@EnableCaching
@SpringBootApplication
public class MyApp { }


Spring по умолчанию использует простой in-memory кеш (ConcurrentHashMap), но можно подключить Caffeine, Redis, Ehcache и т.д.

🔍 Продвинутые фишки:

🎯 Ключ кеша по полям:

@Cacheable(value = "products", key = "#category + ':' + #limit")
public List<Product> getTopProducts(String category, int limit) { ... }


⛔️ Пропуск кеша при null:

@Cacheable(value = "data", unless = "#result == null")
public Data fetchData(String key) { ... }


🔁 Обновление кеша вручную:

@CachePut("users")
public User updateUser(User user) { ... }


🧹 Очистка кеша:

@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) { ... }



🗣 Запомни:@Cacheable — это «копим и не дёргаем зря».
С ним ты ускоряешь работу приложения без лишнего кода, особенно если есть дорогие вызовы (БД, сеть, парсинг).
Please open Telegram to view this post
VIEW IN TELEGRAM
👍155👌3🔥2
Media is too big
VIEW IN TELEGRAM
☕️ Java - Полный Курс по Java

Этот курс охватывает основы Java, включая установку JDK, работу с переменными, условными операторами, циклами и объектно-ориентированным программированием. Подходит для тех, кто только начинает знакомство с языком


🤩 Java Фишки и трюки || #Видео
Please open Telegram to view this post
VIEW IN TELEGRAM
👾2👍1
⌨️ Что такое класс Object? Какие в нем есть методы?

Object это базовый класс для всех остальных объектов в Java. Любой класс наследуется от Object и, соответственно, наследуют его методы:

public boolean equals(Object obj) – служит для сравнения объектов по значению;

int hashCode() – возвращает hash код для объекта;

String toString() – возвращает строковое представление объекта;

Class getClass() – возвращает класс объекта во время выполнения;

protected Object clone() – создает и возвращает копию объекта;

void notify() – возобновляет поток, ожидающий монитор;

void notifyAll() – возобновляет все потоки, ожидающие монитор;

void wait() – остановка вызвавшего метод потока до момента пока другой поток не вызовет метод notify() или notifyAll() для этого объекта;

void wait(long timeout) – остановка вызвавшего метод потока на определённое время или пока другой поток не вызовет метод notify() или notifyAll() для этого объекта;

void wait(long timeout, int nanos) – остановка вызвавшего метод потока на определённое время или пока другой поток не вызовет метод notify() или notifyAll() для этого объекта;

protected void finalize() – может вызываться сборщиком мусора в момент удаления объекта при сборке мусора.

#java #Object #methods
Please open Telegram to view this post
VIEW IN TELEGRAM
👍83
📈 Покрытие кода с JaCoCo — видишь всё, что тесты реально проверяют

Нужен простой способ понять, какие строки кода вообще исполняются при тестировании?
JaCoCo делает это красиво: запускаешь тесты — получаешь отчёт в HTML с краской по строкам.


🔧 Пример настройки под Maven:

В pom.xml добавляешь:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.10</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>


Теперь просто запускаешь:
mvn clean verify


После этого открой отчёт:
open target/site/jacoco/index.html


🎨 Там ты увидишь список классов, методов, строки — зелёные (исполнялись), красные (нет).

👀 Пример из жизни:

Есть метод:
public int divide(int a, int b) {
if (b == 0) throw new IllegalArgumentException("zero");
return a / b;
}

Если тесты вызывают только divide(10, 2) — то строка с исключением будет красной (не покрыта).
Значит, ты пропустил случай деления на 0 — тест не полный.

📌 Хоть это и "плагин", на практике — очень мощный инструмент: видишь, где тесты работают, а где просто "для галочки".

Тесты без покрытия — это как замок на двери без ключа. Видимость есть, защиты нет.


🗣️ Запомни: JaCoCo не требует сложной настройки, но даёт мощную обратную связь. Смотришь отчёт — видишь, где твой код «голый». А дальше решаешь: прикрыть или оставить так.
Please open Telegram to view this post
VIEW IN TELEGRAM
5👨‍💻1
🔄 Observer на чистом Java — реакция без Spring и магии

Нужно, чтобы один объект реагировал на изменения другого? Без тайных фреймворков, просто на Java?

Решение — паттерн Наблюдатель (Observer). Он позволяет подписчикам автоматически узнавать об изменениях.

📦 Минимальный пример:
// Observable (Subject)
class NewsAgency {
private List<NewsListener> listeners = new ArrayList<>();

public void addListener(NewsListener l) {
listeners.add(l);
}

public void publish(String news) {
for (NewsListener l : listeners) {
l.update(news);
}
}
}

// Observer (Listener)
interface NewsListener {
void update(String news);
}

// Конкретный подписчик
class TelegramBot implements NewsListener {
public void update(String news) {
System.out.println("🔔 Telegram получил: " + news);
}
}


▶️ Использование:
public class Main {
public static void main(String[] args) {
NewsAgency agency = new NewsAgency();
agency.addListener(new TelegramBot());

agency.publish("Java 21 уже вышел!");
agency.publish("🧵 Loom теперь в preview!");
}
}


📤 Вывод:
🔔 Telegram получил: Java 21 уже вышел!
🔔 Telegram получил: 🧵 Loom теперь в preview!


🛠 Можно сделать гибче:

Добавь нескольких подписчиков:
class EmailNotifier implements NewsListener {
public void update(String news) {
System.out.println("📧 Email-рассылка: " + news);
}
}

agency.addListener(new EmailNotifier());

Теперь все слушатели получают событие одновременно.


🗣️ Запомни: Паттерн Observer — отличный способ организовать реактивное поведение без зависимости от GUI, фреймворков или событийных систем. Работает в CLI, бэкенде, десктопе и даже Arduino. Просто и гибко.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18👨‍💻43🔥1
☕️ Хватит писать циклы! Java 8 дала тебе больше

С 8-й версии Java предлагает мощные инструменты для работы с коллекциями — и пора ими воспользоваться. Забудь про for и while, когда можно писать элегантно и декларативно.

В статье ты найдёшь:
📌 10 лучших методов из Stream API, которые экономят строки кода
📌 Как заменить громоздкие циклы одной строкой
📌 Примеры filter(), map(), collect() и других трюков
📌 Объяснение, почему функциональный стиль — это не боль, а кайф
📌 Практические сценарии: фильтрация, преобразование, группировка, подсчёты

➡️ Читайте и наслаждайтесь

🗣️ Пиши меньше, делай больше. Stream API — must-have для современного джависта.

🤩 Java Фишки и трюки || #Cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥82❤‍🔥2👍2
🌐 WebClient — современная замена RestTemplate в Java


RestTemplate давно знаком, но теперь Spring рекомендует использовать WebClient. Это не просто новый способ сделать HTTP-запросы — это полноценный инструмент, который умеет работать асинхронно, поддерживает реактивность и даёт гораздо больше контроля над процессом.

Вот как выглядит простой GET-запрос:
WebClient client = WebClient.create();

String body = client.get()
.uri("https://api.github.com/users/octocat")
.retrieve()
.bodyToMono(String.class)
.block();

System.out.println(body);

Здесь bodyToMono(String.class) возвращает реактивный тип Mono, который содержит результат. Если вызвать .block(), запрос будет выполняться синхронно, так что можно легко внедрять WebClient даже в привычный код.

Для POST-запроса с телом используем:

WebClient client = WebClient.create("https://httpbin.org");

String response = client.post()
.uri("/post")
.header("Content-Type", "application/json")
.bodyValue("{\"name\":\"PyLinux\"}")
.retrieve()
.bodyToMono(String.class)
.block();

System.out.println(response);


Ошибки обрабатываются через onStatus, например, для 4xx:
client.get()
.uri("https://api.github.com/404")
.retrieve()
.onStatus(status -> status.is4xxClientError(), resp -> {
System.out.println("Ошибка клиента: " + resp.statusCode());
return Mono.error(new RuntimeException("Client error"));
})
.bodyToMono(String.class)
.block();


Если нужно передать заголовки или параметры:
WebClient client = WebClient.builder()
.baseUrl("https://api.example.com")
.defaultHeader("Authorization", "Bearer your_token")
.build();

String data = client.get()
.uri(uriBuilder -> uriBuilder
.path("/data")
.queryParam("limit", 10)
.build())
.retrieve()
.bodyToMono(String.class)
.block();


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


🗣️ Запомни: WebClient — это не просто новый класс. Это современный подход к HTTP в Java, который ты сможешь использовать и в обычных приложениях, и в реактивных. Если хочешь гибкости и мощи — забудь про RestTemplate и сразу учись WebClient.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍104❤‍🔥3💅2🔥1
Media is too big
VIEW IN TELEGRAM
☕️ Что такое Project Loom?

Этот курс объясняет, что такое Project Loom в Java, включая виртуальные потоки, улучшение масштабируемости и новые возможности многозадачности. Подходит для разработчиков, интересующихся современными подходами к многозадачности в Java.


🤩 Java Фишки и трюки || #Видео
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21🔥1
☕️ List.of() в Java — быстро, но не всегда безопасно

С Java 9 появился удобный способ создать список:
List<String> names = List.of("Alice", "Bob", "Charlie");

Выглядит лаконично, работает быстро — но есть нюанс.

⚠️ Подводные камни

1️⃣.📛 Список неизменяемый
List<String> list = List.of("a", "b");
list.add("c"); // 💥 UnsupportedOperationException
list.remove("a"); // 💥 тоже ошибка

Любая попытка изменить список — ошибка во время выполнения. Это не ArrayList, а immutable List.

2️⃣.💣 Нельзя null
List<String> list = List.of("hello", null);  // 💥 NullPointerException

Даже один null — и всё падает. Потому что List.of() не допускает null ни в одном элементе.

3️⃣.🎭 Не всегда List, который ты ожидаешь
System.out.println(List.of("a", "b").getClass());
// class java.util.ImmutableCollections$ListN

Это не ArrayList, не LinkedList. Это внутренний тип, оптимизированный под неизменяемость.

Если твой код ждёт ArrayList и будет кастить — ловишь ClassCastException.

🧪 Где безопасно использовать:

🟢 Константные списки (List.of(DAYS))
🟢 Аргументы в методах, где ничего не модифицируется
🟢 Когда 100% уверен, что null нет

Альтернатива с возможностью изменения:
List<String> modifiable = new ArrayList<>(List.of("a", "b", "c"));
modifiable.add("d"); // 👍 теперь можно


🗣️ Запомни: List.of() — круто для коротких, неизменяемых данных.
Но если планируешь менять список или есть шанс на nullлучше явно используй `ArrayList`.
Не пались на удобстве — знай, что лежит под капотом.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥135
🧵 Используй try-with-resources с потоками правильно (и продвинуто)

Если ты до сих пор закрываешь потоки руками или думаешь, что try-with-resources — это только для файлов, смотри:

🛠 Пример 1: чтение и закрытие автоматически
try (BufferedReader reader = Files.newBufferedReader(Path.of("data.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}


☑️ Поток закрывается автоматически — даже если внутри случится исключение.


🧪 Пример 2: кастомный ресурс (любой AutoCloseable)
public class TempResource implements AutoCloseable {
public void doSomething() {
System.out.println("Работаем с ресурсом");
}

@Override
public void close() {
System.out.println("Ресурс закрыт");
}
}

try (TempResource res = new TempResource()) {
res.doSomething();
}

🧠 Всё, что реализует AutoCloseable, можно оборачивать в try-with-resources. Это не только файлы, но и сетевые соединения, стримы, логи, сессии Hibernate и др.

🕸 Пример 3: несколько ресурсов
try (
InputStream in = new FileInputStream("input.txt");
OutputStream out = new FileOutputStream("output.txt")
) {
in.transferTo(out);
}

🔒 Все ресурсы закроются в обратном порядке.


🗣️ Запомни: try-with-resources — не просто синтаксический сахар. Это способ писать надёжный код без утечек ресурсов и без лишнего шаблонного кода. Особенно полезно при работе с сетью, файлами, базами данных и внешними API.
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍6🔥4
🧠 Java и AI: как использовать LangChain4J в 2025

Считаешь Java не для AI? Серьёзно ошибаешься! LangChain, фреймворк для разработки с языковыми моделями, теперь уже доступен и для Java — через LangChain4J.

В статье ты узнаешь:

📌 Как использовать LangChain4J для создания цепочек запросов с LLM
📌 Взаимодействие с векторными хранилищами и RAG
📌 Примеры кода на Java для NLP-задач
📌 Почему Java‑специалистам уже пора в AI

➡️ Читайте и наслаждайтесь

🗣️ Java всё ближе к языкам будущего. Попробуй новое направление уже сейчас!

🤩 Java Фишки и трюки || #Cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍42🔥2👏1
🌀 Pattern Matching в Java — прощай `instanceof + cast`

Раньше, чтобы проверить тип и привести его, писали вот так:
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.toLowerCase());
}

👎 Шумно, опасно, повторяется.

С Java 16+ можно проще и безопаснее — паттерн-матчинг для `instanceof`:

✔️ Как это работает:
if (obj instanceof String s) {
System.out.println(s.toLowerCase());
}

Если objString, то переменная s уже приведена к нужному типу.
Больше никаких ручных кастов.

🛠 Примеры на практике:

☑️ Проверка нескольких типов
void printInfo(Object obj) {
if (obj instanceof String s) {
System.out.println("Строка: " + s.toUpperCase());
} else if (obj instanceof Integer i) {
System.out.println("Число: " + (i * 2));
} else {
System.out.println("Что-то другое");
}
}

🔍 Код стал чище: без каста, без дублирования obj.

🚀 Использование внутри switch

С Java 21 (preview) можно использовать switch с типами:
static String format(Object obj) {
return switch (obj) {
case String s -> "Строка: " + s;
case Integer i -> "Целое: " + i;
case null -> "null";
default -> "Неизвестно";
};
}

➡️ Это называется Pattern Matching for switch.

🧩 Совмещение с guard'ами
if (obj instanceof String s && s.length() > 5) {
System.out.println("Длинная строка: " + s);
}

⚠️ s будет доступна только если оба условия выполняются. Это безопасно.

🧪 Более сложные условия
if (!(obj instanceof String s)) return;
System.out.println("Обрабатываем строку: " + s.toLowerCase());

Можно комбинировать с !instanceof, return, continue, break и др.

🗣️ Запомни: Используй instanceof с привязкой переменной — особенно в if-else, парсерах, логике обработки событий и switch.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍133🔥2👨‍💻1
🚀 Java Stream API: продвинутые приёмы и подводные камни

Stream API — мощный инструмент, но легко попасть в ловушку, если не знать нюансов.

Фишки, которые нужно знать

🟢 Фильтрация и преобразование в одну строку:
List<String> names = users.stream()
.filter(u -> u.isActive())
.map(User::getName)
.collect(Collectors.toList());


🟢 Собрать в Map без дублирующих ключей:
Map<Long, String> map = users.stream()
.collect(Collectors.toMap(
User::getId,
User::getName,
(a, b) -> a // если дубликат — оставить первый
));


🟢 Группировка и сортировка:
Map<String, List<User>> grouped = users.stream()
.collect(Collectors.groupingBy(User::getRole));


⚠️ Подводные камни

🟢 Не перезапускается!
Stream<String> stream = list.stream();
stream.forEach(System.out::println);
// stream.forEach(...) // выбросит исключение — уже использован


🟢 Ленивая природа:
Stream.of("a", "b", "c")
.filter(s -> {
System.out.println("filter: " + s);
return true;
});
// ничего не произойдёт, пока не вызвать .collect() или .forEach()


🟢 Null внутри Stream — плохая идея:
Stream.of("a", null, "b");  //  NPE при map/filter


Лучше фильтровать:
Stream.of("a", null, "b")
.filter(Objects::nonNull)
.map(String::toUpperCase)
.forEach(System.out::println);


🔍 Продвинутый пример

Фильтруем активных, сортируем по дате, берём 10 последних:
List<Post> recent = posts.stream()
.filter(Post::isActive)
.sorted(Comparator.comparing(Post::getCreatedAt).reversed())
.limit(10)
.collect(Collectors.toList());


🗣️ Запомни: Stream API — кайф, если понимаешь, что делаешь.
Всегда помни про однократность, лень и null — и всё будет летать.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍156🔥2❤‍🔥1
⚙️ Оптимизация Collections и Stream API — как это делать профессионально

Используешь Stream в Java 8+? Только не думай, что это всегда просто и быстро. В этой статье — реальные кейсы и трюки, которые позволят ускорить обработку коллекций и избежать типичных ошибок.

В статье ты узнаешь:

📌 Лучшие приёмы работы со Stream, чтобы избежать лишней аллокации
📌 Когда Stream быстрее цикла, а когда цикл — всё же король производительности
📌 Практические советы: избегать лишних объектов, использовать правильные методы сборки
📌 Ускорение благодаря профайлингу и тому, как выжать максимум из JIT

➡️ Читайте и наслаждайтесь

🗣️ Java всегда сильна в коллекциях — сделай свой код быстрее и чище уже сегодня!

🤩 Java Фишки и трюки || #Cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
💎 Clean Code на Java — идиоматические приёмы, которые реально работают

Хочешь писать Java-код, который приятно читать и легко сопровождать?
Вот не теория с книжек, а настоящие идиомы, шаблоны и фишки, которые делают код чистым, понятным и «живым».

👍 1. Именование — полдела

Плохо:
double d = get(a, b);


✔️Лучше:
double distance = calculateDistance(startPoint, endPoint);

Именуй переменные и методы так, чтобы код сам говорил, что он делает.

👍 2. if без else — код легче читать

Было:
if (isAdmin) {
grantAccess();
} else {
denyAccess();
}


✔️ Стало:
if (!isAdmin) {
denyAccess();
return;
}
grantAccess();


Меньше вложенности → легче читать.

👍 3. Меньше булевых флагов

Неочевидно:
public void start(boolean silent) {
if (!silent) {
System.out.println("Starting...");
}
// ...
}


✔️ Читаемо:
public void startLoud() {
System.out.println("Starting...");
start();
}

public void start() {
// ...
}

Выноси поведение в отдельные методы, а не в булевы флаги.

👍 4. Используй Optional вместо null

Потенциальный NPE:
String name = user.getName();


✔️ Безопаснее:
Optional<String> name = user.getNameOptional();
name.ifPresent(System.out::println);

Optional показывает, что значение может отсутствовать.

👍 5. Выражай намерение через enum

Магические числа:
send(2);


✔️ Ясно:
send(Priority.HIGH);

enum передаёт смысл.

👍 6. Строим объекты читаемо: builder

Плохо читается:
User u = new User("Ann", 25, true, "Russia", null, false);


✔️ Круто:
User user = User.builder()
.name("Ann")
.age(25)
.active(true)
.country("Russia")
.build();

Именованные параметры через builder — читабельность x10.

👍 7. Используй switch-expression в Java 14+

Старый подход:
int days;
switch (month) {
case JANUARY: days = 31; break;
case FEBRUARY: days = 28; break;
// ...
}


✔️ Современный:
int days = switch (month) {
case JANUARY, MARCH, MAY -> 31;
case FEBRUARY -> 28;
default -> throw new IllegalArgumentException();
};

Чётко, лаконично, без лишнего кода.

👍 8. Чистые методы = маленькие и простые

Монстр:
public void registerUser(UserDto dto) {
validate(dto);
saveToDatabase(dto);
sendWelcomeEmail(dto);
logRegistration(dto);
}


✔️ Разбиваем:
public void registerUser(UserDto dto) {
validate(dto);
persist(dto);
notify(dto);
}

private void validate(UserDto dto) { ... }
private void persist(UserDto dto) { ... }
private void notify(UserDto dto) { ... }

Каждый метод делает одну вещь. Легко тестировать, легко читать.

👍 9. Предпочитай Streams + map/filter/collect

Старый for:
List<String> active = new ArrayList<>();
for (User u : users) {
if (u.isActive()) {
active.add(u.getName().toUpperCase());
}
}


✔️ Современно:
List<String> active = users.stream()
.filter(User::isActive)
.map(u -> u.getName().toUpperCase())
.collect(Collectors.toList());

Чисто, выразительно, без шума.

👍 10. Старайся не ловить Exception без причины

Так себе:
try {
Thread.sleep(100);
} catch (Exception e) {
// игнорируем
}


✔️ Так лучше:
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}

Нельзя просто проглатывать ошибки — это превращается в хаос.


🗣️ Запомни:
Clean code — это не строгость, а удобство.

Читаемый код — это код, который ты поймёшь через 3 месяца в 2 часа ночи.
Не бойся переписывать, выносить, называть по-человечески — в этом сила Java-разработчика.
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍7🔥4❤‍🔥2👎2🥰1💯1