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

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

✍️По всем вопросам: @Pascal4eg
Download Telegram
Что выведет код?
Anonymous Quiz
50%
60
31%
60000
19%
3600000
🥱11👍3👏2🎉1
⌨️ Какие побитовые операции вы знаете?

~ Побитовый унарный оператор NOT;

& Побитовый AND;

&= Побитовый AND с присваиванием;

| Побитовый OR;

|= Побитовый OR с присваиванием;

^ Побитовый исключающее XOR;

^= Побитовый исключающее XOR с присваиванием;

>> Сдвиг вправо (деление на 2 в степени сдвига);

>>= Сдвиг вправо с присваиванием;

>>> Сдвиг вправо без учёта знака;

>>>= Сдвиг вправо без учёта знака с присваиванием;

<< Сдвиг влево (умножение на 2 в степени сдвига);

<<= Сдвиг влево с присваиванием.

#java #bitwise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍81🔥1
⌨️ Почему 1==1 это true, а 128==128 это false?


Integer a = 128;
Integer b = 128;
System.out.println(a == b); // false

Integer x = 1;
Integer y = 1;
System.out.println(x == y); // true


Это не просто волшебство! Это связано с целочисленным кэшированием в Java.

Для значений в диапазоне от -128 до 127 объекты типа Integer кэшируются, и ссылки на них одинаковы, а для значений за пределами этого диапазона создаются новые объекты, и ссылки на них будут разными. Так как используется оператор ==, то сравниваются ссылки на объекты.

#java #magic
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🤔174👏1🌭1
⌨️ Метод reduce интерфейса Stream

Метод reduce в интерфейсе Stream используется для сведения набора элементов потока к одному результату, применяя заданную бинарную операцию (например, сложение, умножение). Этот метод часто используется для агрегации данных.

Допустим, у нас есть список чисел, и мы хотим найти их сумму:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);

System.out.println(sum); // 15

В этом примере:
0 — начальное значение (identity),
(a, b) -> a + b — бинарная операция, которая складывает два значения.

reduce полезен для таких операций, как сумма, произведение, объединение строк и т.д.

#java #Stream #reduce
Please open Telegram to view this post
VIEW IN TELEGRAM
👍81🔥1
⌨️ Arrays.deepToString()

Метод deepToString из класса Arrays используется для создания строкового представления многомерных массивов (например, массивов массивов). Он обходит каждый уровень вложенности массива и выводит его элементы в виде строки. Это удобно для работы с многомерными массивами, так как стандартный метод toString не раскрывает их структуру.

Пример использования:

int[][] array = {{1, 2, 3}, {4, 5, 6}};
System.out.println(Arrays.deepToString(array));
// [[1, 2, 3], [4, 5, 6]]

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

#java #Arrays #deepToString
Please open Telegram to view this post
VIEW IN TELEGRAM
👍132
⌨️ Параллельные и последовательные потоки (Stream)

Последовательные потоки (Sequential Streams)

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

✔️ Используют основной поток программы (main thread) для выполнения операций.

✔️ Метод stream() создаёт последовательный поток.

Пример последовательного потока:

List<String> list = List.of("Hello ", "w", "o", "r", "l", "d!");
list.stream().forEach(System.out::print);
// Hello world!


Параллельные потоки (Parallel Streams)

✔️ Обрабатывают элементы параллельно, распределяя их между несколькими потоками (threads), что позволяет использовать многопоточность.

✔️ Используют ForkJoinPool для распределения задач между потоками.

✔️ Эффективны для больших наборов данных, поскольку могут улучшить производительность на многоядерных процессорах.

✔️ Параллельный поток можно создать, вызвав метод parallelStream() или применив метод parallel() к уже существующему потоку.

Пример параллельного потока:

List<String> list = List.of("Hello ", "w", "o", "r", "l", "d!");
list.parallelStream().forEach(System.out::print);
// rlHello d!wo


#java #Stream #parallelStream
Please open Telegram to view this post
VIEW IN TELEGRAM
👍112🔥1😁1
⌨️ ForkJoinPool — это специальная реализация пула потоков, предназначенная для выполнения параллельных задач с использованием алгоритма разделяй и властвуй (divide and conquer). Этот пул потоков был представлен в Java 7 как часть библиотеки java.util.concurrent.

Использует подход "разделяй и властвуй", где задача разбивается на подзадачи до тех пор, пока они не станут достаточно маленькими для последовательного решения. Для этого используются классы RecursiveTask<V> (возвращает результат) и RecursiveAction (без результата).

ForkJoinPool динамически управляет количеством потоков, при необходимости создавая новые. Обычно это количество соответствует числу процессоров, доступных в системе.

Использует технику work-stealing, где потоки, завершившие свои задачи, могут "красть" задачи у других потоков, чтобы эффективно использовать ресурсы процессора.

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

Основные методы:

invoke(): синхронно запускает задачу и ждет её завершения.

submit(): запускает задачу асинхронно.

execute(): также запускает задачу асинхронно, но не возвращает результат.

Пример использования:

import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;

class SumTask extends RecursiveTask<Integer> {
private final int[] array;
private final int start, end;
private final int threshold = 10;

public SumTask(int[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}

@Override
protected Integer compute() {
if (end - start <= threshold) {
// Базовый случай: небольшая задача
int sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
} else {
// Разделяем задачу
int mid = (start + end) / 2;
SumTask leftTask = new SumTask(array, start, mid);
SumTask rightTask = new SumTask(array, mid, end);

leftTask.fork(); // Асинхронно запускаем левую подзадачу
int rightResult = rightTask.compute(); // Синхронно вычисляем правую подзадачу
int leftResult = leftTask.join(); // Ждем завершения левой подзадачи

return leftResult + rightResult;
}
}
}

public class ForkJoinExample {
public static void main(String[] args) {
ForkJoinPool pool = new ForkJoinPool();
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
SumTask task = new SumTask(array, 0, array.length);
int result = pool.invoke(task);
System.out.println("Сумма: " + result);
}
}

Этот код создает задачу для суммирования массива, разбивая его на подзадачи.

#java #ForkJoinPool
Please open Telegram to view this post
VIEW IN TELEGRAM
👍141🔥1
⌨️ StringJoiner - это класс, который предназначен для объединения строк с использованием разделителя между ними. Этот класс был введен в Java 8 в пакете java.util. Он облегчает создание текстовых последовательностей, объединяя строки и вставляя разделители между ними.

Вызов метода toString() возвращает объединенную строку с разделителями и окружающими символами.

Вы также можете использовать метод setEmptyValue() для определения значения, которое будет использоваться, если StringJoiner остается пустым.


StringJoiner sj = new StringJoiner(", ", "[" , "]");
sj.setEmptyValue("No items");
System.out.println(sj.toString()); // No items

sj.add("Apple").add("Banana").add("Cherry");
System.out.println(sj.toString()); // [Apple, Banana, Cherry]


#java #StringJoiner
Please open Telegram to view this post
VIEW IN TELEGRAM
👍181
⌨️ Метод forEachOrdered интерфейса Stream

Метод forEachOrdered в интерфейсе Stream используется для обработки каждого элемента потока с сохранением порядка обработки, даже если поток является параллельным.

В отличие от метода forEach(), который не гарантирует порядок выполнения в параллельных потоках, метод forEachOrdered() всегда сохраняет порядок элементов, как если бы поток был последовательным.

Этот метод полезен, если вам нужно выполнить действия для каждого элемента в параллельном потоке, но при этом важен порядок обработки (например, вывод или запись данных в определенной последовательности).

Параллельный поток с forEach:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.parallelStream().forEach(n -> System.out.println(n));
// Порядок не определён, например 3 1 4 2 5


Параллельный поток с forEachOrdered:

numbers.parallelStream()
.forEachOrdered(n -> System.out.println(n));
// 1 2 3 4 5


#java #Stream #forEachOrdered
Please open Telegram to view this post
VIEW IN TELEGRAM
👍122
⌨️ Почему Java не поддерживает перегрузку операторов?

Перегрузка операторов делает код менее читаемым и плохо поддерживаемым. Чтобы сохранить простоту кода, Java не поддерживает перегрузку операторов.

#java #operatorOverloading
Please open Telegram to view this post
VIEW IN TELEGRAM
5
😁39🤣112🐳1
public class Quest {
public static void main(String[] args) {
Integer a = 128;
Integer b = 128;
System.out.print(a == b);

System.out.print("-");

Integer x = 1;
Integer y = 1;
System.out.print(x == y);
}
}

#java #quest
👍21
Что выведет код?
Anonymous Quiz
30%
true-true
4%
true-false
53%
false-true
13%
false-false
🎉43
⌨️ Stream.reduce() vs Collectors.joining()

Когда требуется конкатенировать строки с использованием Stream, можно выбрать один из двух методов: Stream.reduce() или Stream.collect(Collectors.joining()).

Пример с Stream.reduce():
List<String> list = List.of("Str1", "Str2", "Str3");
String result = list.stream().reduce("", (a, b) -> a + b);
System.out.println(result); // Str1Str2Str3


Пример с Collectors.joining():
List<String> list = List.of("Str1", "Str2", "Str3");
String result = list.stream().collect(Collectors.joining());
System.out.println(result); // Str1Str2Str3


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

В свою очередь, метод Collectors.joining() использует StringBuilder для сборки строк, что значительно эффективнее. Он избегает создания лишних объектов и снижает потребление памяти.

#java #Stream #reduce #joining
Please open Telegram to view this post
VIEW IN TELEGRAM
👍163🍾2🔥1
⌨️ Вычислить максимальное значение в одну строку

В этом нам помогут наши любимые стримы.

Так:
List<Integer> iList = List.of(1,2,3,4,5);
Integer max = iList.stream().reduce(Integer::max).orElse(null);
System.out.println(max);


А еще лучше вот так:
List<Integer> iList = List.of(1,2,3,4,5);
iList.stream().reduce(Integer::max).ifPresent(System.out::println);


#java #Stream #max
Please open Telegram to view this post
VIEW IN TELEGRAM
👍91
⌨️ Несколько способов избежать NullPointerException:

✔️ Используйте класс Optional из пакета java.util для работы с потенциально пустыми значениями.

✔️ При сравнении константы с переменной, полученной извне, вызывайте метод equals() на константе, а не на переменной.

✔️ Для сравнения двух переменных используйте метод java.util.Objects#equals.

✔️ Применяйте библиотеки, обеспечивающие null-безопасность, например, Apache Commons StringUtils.

✔️ Всегда вызывайте методы equals() и equalsIgnoreCase() на объектах, которые гарантированно не равны null.

✔️ Вместо метода toString(), который может вызвать NullPointerException, используйте String.valueOf().

✔️ Используйте аннотации @NotNull и @Nullable, доступные в вашей IDE, для указания допустимости null.

✔️ Возвращайте пустую коллекцию (например, java.util.Collections#emptyList) вместо null при работе с коллекциями в методах.

#java #NullPointerException #Optional
Please open Telegram to view this post
VIEW IN TELEGRAM
👍164🔥1👏1
⌨️ Семейство классов *SummaryStatistics

Классы DoubleSummaryStatistics, IntSummaryStatistics и LongSummaryStatistics служат для хранения агрегированных данных о числовом потоке. А конкретно: количество, сумма, минимальное, максимальное и среднее.

Пример:

List<Integer> iList = List.of(1, 2, 3);
IntSummaryStatistics stats = iList.stream().collect(Collectors.summarizingInt(i -> i));
System.out.println(stats);
// IntSummaryStatistics{count=3, sum=6, min=1, average=2,000000, max=3}


#java #IntSummaryStatistics #DoubleSummaryStatistics #LongSummaryStatistics
Please open Telegram to view this post
VIEW IN TELEGRAM
👍91
⌨️ Логические операторы

«И» (AND): конъюнкция, логическое умножение

true && true = true
false && false = false
true && false = false
false && true = false

true & true = true
false & false = false
true & false = false
false & true = false

Побитовые операции:
1010
&&&&
1001
====
1000


Включающее «ИЛИ» (OR): дизъюнкция, логическое сложение

true || true = true
false || false = false
true || false = true
false || true = true

true | true = true
false | false = false
true | false = true
false | true = true

Побитовые операции:
1010
||||
1001
====
1011


Исключающее «ИЛИ» (XOR): строгая дизъюнкция, логическое вычитание

true ^ true = false
false ^ false = false
true ^ false = true
false ^ true = true

Побитовые операции:
1010
^^^^
1001
====
0011


«НЕ» (NOT): инверсия, отрицание

!true = false
!false = true

Побитовый унарный оператор NOT:
~~
01
==
10



Порядок выполнения операторов

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

! ~ (NOT)
& (AND)
^ (XOR)
| (OR)
&& (условный AND)
|| (условный OR)

Если одинаковые операции стоят по соседству, то раньше выполняется та, что левее.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍112
public class Survive {
private Survive internalInstance = new Survive();

public Survive() throws Exception {
throw new Exception("I'm not coming out");
}

public static void main(String[] args) {
try {
Survive b = new Survive();
System.out.println("WIN!");
} catch (Exception ex) {
System.out.println("LOSE!");
}
}
}


#java #quest