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

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

✍️По всем вопросам: @Pascal4eg
Download Telegram
⌨️ Интерфейс CharSequence

Интерфейс CharSequence представляет собой последовательность символов и является базовым интерфейсом для работы с различными строковыми типами. Он был введён в Java начиная с версии 1.4 и служит для предоставления общего интерфейса для объектов, которые могут быть представлены как последовательность символов.

CharSequence реализован такими классами, как:
String — неизменяемая строка.
StringBuilder — изменяемая последовательность символов.
StringBuffer — изменяемая, но потокобезопасная последовательность символов.

CharSequence определяет несколько методов, которые предоставляют доступ к символам последовательности и информации о ней:

int length();

Возвращает количество символов в последовательности.


char charAt(int index);

Возвращает символ по указанному индексу.


CharSequence subSequence(int start, int end);

Возвращает новую последовательность символов, которая является подстрокой оригинальной последовательности. Индекс start включается, а end — нет.


String toString();

Возвращает строковое представление последовательности символов.


CharSequence cs = "Hello, World!";
System.out.println("Length: " + cs.length());
System.out.println("Char at index 1: " + cs.charAt(1));
System.out.println("Subsequence (0, 5): " + cs.subSequence(0, 5));
System.out.println("String: " + cs.toString());


Вывод:

Length: 13
Char at index 1: e
Subsequence (0, 5): Hello
String: Hello, World!


#java #CharSequence
Please open Telegram to view this post
VIEW IN TELEGRAM
8🥰1
public class Quest {
public static void main(String[] args) {
int i = Integer.MAX_VALUE;
i++;
if (i == 0) {
System.out.println("ZERO");
} else if (i == Integer.MIN_VALUE) {
System.out.println("MIN");
}
}
}

#java #quest
2
🔥71🤔1🎉1
⌨️ Пропуск элементов потока. Метод skip

Потоки данных поддерживают метод skip(n), возвращающий поток данных с отброшенными первыми n элементами источника. Если в потоке-источнике было меньше n элементов, возвращается пустой поток.

Например, следующий код пропускает первые два блюда, содержащие более 300 калорий, и возвращает остальные:

List<Dish> dishes = menu
.stream()
.filter(d -> d.getCalories() > 300)
.skip(2)
.collect(toList());


#java #stream #skip
Please open Telegram to view this post
VIEW IN TELEGRAM
👏73
⌨️ Вчера вышла Java 23

Внутри много интересного, например Markdown документация, поддержка примитивных типов в паттернах и операторах instanceof / switch и многое другое.

Появился еще один тип классов - неявный, как будто существующих нам было мало 😁

Теперь приложение может стартовать даже если метод main не статический и не содержит параметр String[] args:

// --enable-preview --source 23
class HelloWorld {
void main() {
System.out.println("Hello, World!");
}
}

В таком случае во время запуска JVM сама создаст экземпляр класса HelloWorld и вызовет у него метод main():

$ java --enable-preview --source 23 HelloWorld.java
Hello, World!


И даже вот так!:

// HelloWorld.java

String greeting = "Hello, World!";

void main() {
println(greeting);
}

То есть вообще не объявляя класса! В таком случае виртуальная машина сама объявит неявный класс, в который поместит метод main() и другие верхнеуровневые объявления в файле. Фишка здесь еще и в том что используется метод println() вместо System.out.println(), это возможно из-за того что в неявный класс по умолчанию импортируется новый класс java.io.IO, в котором есть соответствующий метод.

Подробнее можно почитать на Habr'е.

#java23
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍14😢84
💎 Проблема ромба (Diamond problem)

Ромбовидное наследование (diamond inheritance) — ситуация в объектно-ориентированных языках программирования с поддержкой множественного наследования, когда два класса B и C наследуют от A, а класс D наследует от обоих классов B и C. При этой схеме наследования может возникнуть неоднозначность: если объект класса D вызывает метод, определенный в классе A (и этот метод не был переопределен в классе D), а классы B и C по-своему переопределили этот метод, то от какого класса его наследовать: B или C?

В Java множественное наследование не разрешено для классов и разрешено только для интерфейсов, чтобы устранить эту серьезную проблему.

#java #diamond #problem
Please open Telegram to view this post
VIEW IN TELEGRAM
5🥰1
public class Quest {
public static final int END = Integer.MAX_VALUE;
public static final int START = END - 100;

public static void main(String[] args) {
int count = 0;
for (int i = START; i <= END; i++) count++;
System.out.println(count);
}
}

#java #quest
5
⌨️ Метод Stream.anyMatch

Метод anyMatch служит для ответа на вопрос: «Удовлетворяет ли заданному предикату хотя бы один элемент из потока данных?»

Метод anyMatch возвращает boolean, а значит, является завершающей (терминальной) операцией.


int[] digits = {1, 3, 5, 7, 2, 9};
boolean result = Arrays.stream(digits).anyMatch(d -> d % 2 == 0);
System.out.println(result); // true


#java #Stream #anyMatch
Please open Telegram to view this post
VIEW IN TELEGRAM
14
⌨️ Методы allMatch и noneMatch интерфейса Stream

Метод allMatch проверяет, удовлетворяют ли заданному предикату все элементы потока данных.


// Все не чётные?
int[] digits = {1, 3, 5, 7, 9};
boolean result = Arrays.stream(digits).allMatch(d -> d % 2 != 0);
System.out.println(result); // true


Противоположностью allMatch является метод noneMatch. Он проверяет, точно ли ни один элемент списка не соответствует заданному предикату.

// Нет чётных?
int[] digits = {1, 3, 5, 7, 9};
boolean result = Arrays.stream(digits).noneMatch(d -> d % 2 == 0);
System.out.println(result); // true


#java #Stream #allMatch #noneMatch
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
public class Quest {
public static void main(String[] args) {
int minutes = 0;
for (int ms = 0; ms < 60 * 60 * 1000; ms++) {
if (ms % 60 * 1000 == 0) {
minutes++;
}
}
System.out.println(minutes);
}
}

#java #quest
1💘1
Что выведет код?
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