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

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

✍️По всем вопросам: @Pascal4eg
Download Telegram
⌨️ Инициализация это процесс задания начальных значений переменным и объектам перед их использованием. Этот процесс необходим для того, чтобы обеспечить корректное начальное состояние переменных и объектов в программе.

Порядок инициализации

1⃣ Статические переменные: если в классе есть статические переменные, то они будут инициализированы в первую очередь. Переменные будут инициализированы в том порядке в котором идут в коде.

2⃣ Статический блок инициализации: далее сработает блок инициализации статических переменных.

3⃣ Переменные экземпляра

4⃣ Блок инициализации переменных экземпляра

5⃣ Конструктор

Вывод кода:
Static Variables initialized!
Static Initialization Block initialized!
Instance Variables initialized!
Instance Initialization Block initialized!
Constructor initialized!


Инициализация в Java является важным аспектом, который гарантирует, что объекты и переменные находятся в правильном состоянии перед их использованием. Понимание порядка инициализации помогает избегать ошибок и создавать надежные программы на Java.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍135
🥴8💯6🤣4🤩21🖕1
⌨️ В чём заключается разница между методами start() и run() класса Thread?

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

#java #Thread #start #run
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍8
⌨️ В каких состояниях может находиться поток?

Потоки могут находиться в одном из следующих состояний:

✔️ Новый (New). После создания экземпляра потока, он находится в состоянии Новый до тех пор, пока не вызван метод start(). В этом состоянии поток не считается живым.

✔️ Работоспособный (Runnable). Поток переходит в состояние Работоспособный, когда вызывается метод start(). Поток может перейти в это состояние также из состояния Работающий или из состояния Блокирован. Когда поток находится в этом состоянии, он считается живым.

✔️ Работающий (Running). Поток переходит из состояния Работоспособный в состояние Работающий, когда Планировщик потоков выбирает его как работающий в данный момент.

✔️ Живой, но не работоспособный (Alive, but not runnable). Поток может быть живым, но не работоспособным по нескольким причинам:

▪️Ожидание (Waiting). Поток переходит в состояние Ожидания, вызывая метод wait(). Вызов notify() или notifyAll() может перевести поток из состояния Ожидания в состояние Работоспособный.

▪️Сон (Sleeping). Метод sleep() переводит поток в состояние Сна на заданный промежуток времени в миллисекундах.

▪️Блокировка (Blocked). Поток может перейти в это состояние, в ожидании ресурса, такого как ввод/вывод или из-за блокировки другого объекта. В этом случае поток переходит в состояние Работоспособный, когда ресурс становится доступен.

▪️Мёртвый (Dead). Поток считается мёртвым, когда его метод run() полностью выполнен. Мёртвый поток не может перейти ни в какое другое состояние, даже если для него вызван метод start().

#java #Thread #state
Please open Telegram to view this post
VIEW IN TELEGRAM
👍103
⌨️ Срезы в стримах. Метод takeWhile

В Java 9 появилось два новых метода, полезных для выбора элементов потока с хорошей производительностью: takeWhile и dropWhile.

Допустим, у нас есть следующий список блюд:

List<Dish> specialMenu = Arrays.asList(
new Dish("seasonal fruit", 120),
new Dish("prawns", 300),
new Dish("rice", 350),
new Dish("chicken", 400),
new Dish("french fries", 530));


Для получения блюд с калорийностью меньше 320, можно воспользоваться операцией filter. Недостаток операции filter в том, что она требует прохода в цикле по всему потоку данных с применением предиката ко всем элементам.

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

Поможет нам в этом операция takeWhile! Она позволяет выполнить срез любого потока данных (даже бесконечного) с помощью предиката. И, к счастью, она прекращает работу сразу же по обнаружении неподходящего элемента. Вот как ее следует использовать:

List<Dish> sliceMenu1
= specialMenu.stream()
.takeWhile(dish -> dish.getCalories() < 320)
.collect(toList());


#java #stream #takeWhile
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍23🤝21🔥1🤔1
⌨️ Срезы в стримах. Метод dropWhile

Операция dropWhile служит дополнением к операции takeWhile. Она отбрасывает первые элементы, для которых предикат возвращает true. Как только результат вычисления предиката становится ложным, она прекращает работу и возвращает все оставшиеся элементы, причем работает даже в том случае, если число оставшихся элементов бесконечно!


List<Integer> ints = List.of(1,2,3,4,5,6,7,8,9);
ints.stream()
.dropWhile(i -> i < 5)
.forEach(System.out::println);
// 5 6 7 8 9


#java #stream #dropWhile
Please open Telegram to view this post
VIEW IN TELEGRAM
👍183
⌨️ Усечение потока данных. Метод limit

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

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

List<Dish> dishes = specialMenu
.stream()
.filter(dish -> dish.getCalories() > 300)
.limit(3)
.collect(toList());


Метод limit работает и для неупорядоченных потоков данных (например, когда источник представляет собой объект типа Set). В этом случае не следует исходить из допущения о какой-либо упорядоченности результата, возвращенного методом limit.

#java #stream #limit
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝3👍2
От всей души поздравляю всех программистов и им сочувствующих! 🎉

Пусть код всегда будет чистым, как слеза, проекты — увлекательными и вдохновляющими, а коллеги — понимающими и дружелюбными! Желаю тебе легких решений сложных задач и бесконечного потока креатива. Пусть каждый день приносит новые вызовы и радости в мир программирования! 🚀
1🎉31❤‍🔥11
public class Quest {
public static void main(String[] args) {
List<Integer> ints = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
ints.stream()
.filter(i -> i % 2 == 0)
.skip(1)
.limit(1)
.forEach(System.out::print);
}
}

#java #quest
2
Что выведет код?
Anonymous Quiz
14%
<ничего>
11%
2468
57%
4
18%
2
👍5🎉3
⌨️ Классы-обёртки (wrapper classes)

В Java классы-обёртки (wrapper classes) используются для того, чтобы представлять примитивные типы данных как объекты. Это необходимо, так как Java — это объектно-ориентированный язык, и в некоторых случаях, например, при работе с коллекциями, нужно использовать объекты вместо примитивных типов. Для каждого примитивного типа данных существует соответствующий класс-обёртка.

Java автоматически преобразует примитивные типы в соответствующие объекты классов-обёрток и наоборот. Это упрощает код, так как программисту не нужно делать это вручную.

Все классы-обёртки являются неизменяемыми, то есть их значения не могут быть изменены после создания.

Некоторые классы-обёртки, такие как Byte, Short, Integer и Long, кэшируют значения в определённом диапазоне (от -128 до 127), что улучшает производительность при частом использовании этих значений.

#java #wrappers
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍7
⌨️ "Распрямление" потока. Метод flatMap

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

Допустим, у вас есть список строк, каждая из которых содержит несколько слов, и вы хотите получить поток всех слов:

List<String> sentences = Arrays.asList("Java is fun", "I love programming");

Stream<String> wordsStream = sentences.stream()
.flatMap(sentence -> Arrays.stream(sentence.split(" "))); // Преобразуем в поток слов

wordsStream.forEach(System.out::println);


Результат:

Java
is
fun
I
love
programming


Здесь каждый массив слов был преобразован в поток, а затем flatMap "распрямил" эти потоки в один.

#java #stream #flatMap
Please open Telegram to view this post
VIEW IN TELEGRAM
👍81
⌨️ Чем отличаются методы Stream.toList() и Stream.collect(Collectors.toList())?

Методы Stream.toList() и Stream.collect(Collectors.toList()) кажутся схожими, так как оба возвращают список, но есть ключевое отличие: Stream.toList() возвращает неизменяемый список, а Stream.collect(Collectors.toList()) возвращает изменяемый список на базе ArrayList.

#java #stream #toList
Please open Telegram to view this post
VIEW IN TELEGRAM
👍203
⌨️ Чем различаются Thread и Runnable?

Thread - это класс, некоторая надстройка над физическим потоком.

Runnable - это интерфейс, представляющий абстракцию над выполняемой задачей.

Интерфейс Runnable позволяет логически отделить логику выполнения задачи от непосредственного управления потоком.

#java #Thread #Runnable
Please open Telegram to view this post
VIEW IN TELEGRAM
👍62
⌨️ Интерфейс 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