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

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

✍️По всем вопросам: @Pascal4eg
Download Telegram
Считывание файла из стандартного потока ввода

Перенаправление ввода-вывода — возможность командной оболочки ряда операционных систем перенаправлять стандартные потоки в определённое пользователем место, например, в файл. Характерна для Unix-подобных операционных систем, но в разной степени реализована и в операционных системах других семейств.

Перенаправление обычно осуществляется вставкой специального символа > или < после команды.
Обычно синтаксис выглядит так:

команда1 > файл1 — выполняет команду1, помещая стандартный вывод в файл1;

команда1 < файл1 — выполняет команду1, используя в качестве источника ввода файл1 (вместо клавиатуры).

Для перенаправления содержимого файла в поток ввода нашего приложения воспользуемся командой:

java -jar app.jar < file.txt
5❤‍🔥2👍2💘1
⌨️ Использование аннотаций. Аннотации позволяют добавлять метаданные к вашему коду, что может быть полезно для документирования, тестирования и других целей. Вот пример использования аннотации:

import java.lang.annotation.*;

// Создание аннотации
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface MethodInfo {
String author() default "unknown";
String date();
int revision() default 1;
String comments();
}

public class Example {
// Использование аннотации
@MethodInfo(author = "John Doe", date = "2022-08-15", comments = "Example method")
public void performAction() {
// Реализация метода
}
}


В этом примере создается аннотация MethodInfo с параметрами author, date, revision и comments. Затем аннотация применяется к методу performAction. Таким образом, аннотации могут использоваться для предоставления дополнительной информации о вашем коде, что может быть полезно при разработке, тестировании и поддержке проекта.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍31💯1
Методы и конструкторы в enum

Перечисления (enum) — это классы Java, определяющие наборы констант. Самый простой enum выглядит так:


public enum Vehicle { CAR, BUS, BICYCLE, SCOOTER }


Но на самом деле, enum в Java обладают гораздо более широким функционалом. Они поддерживают поля, методы, интерфейсы и т.д. Они также Comparable и Serializable и могут имплементировать все методы объекта.
Для наглядности давайте создадим enum Animal и присвоим каждому элементу цвет:

public enum Animal {
DOG("black"),
CAT("white"),
RAT("gray");

private final String color;
Animal(String color){
this.color = color;
}
public String getColor(){
return color;
}
}


Теперь мы можем выполнить перебор элементов массива с помощью статического метода values():

public class Main {
public static void main(String[] args) {
for (Animal a : Animal.values()) {
System.out.println(a.name() + " - " + a.getColor());
}
}
}


Мы получим следующий результат:

DOG - black
CAT - white
RAT - gray


Каждой константе можно присвоить разное поведение при выполнении определенного метода. Например, можно сделать основной метод абстрактным и переопределить его в каждой константе:

public enum Operation {
PLUS { double evaluate(double x, double y) { return x + y; } },
MINUS { double evaluate(double x, double y) { return x - y; } },
abstract double evaluate(double x, double y);
}


Всё это обеспечивает удобную работу с перечислениями в Java.
👍272🔥2🥰2👏1
JSON – невероятно удобный и полезный формат для хранения и обмена данными. Java полностью поддерживает его.

Сериализовать данные можно так:

JSONObject author = new JSONObject();
author.put("name", "J. K. Rowling");
author.put("numberOfBooks", 22);

JSONArray books = new JSONArray();
books.put("Harry Potter and the Philosopher's Stone");
books.put("Harry Potter and the Chamber of Secrets");
books.put("Harry Potter and the Prisoner of Azkaban");

author.put("books", books);
System.out.print(author);


Получится вот такая JSON-строка:

{"books":["Harry Potter and the Philosopher's Stone","Harry Potter and the Chamber of Secrets","Harry Potter and the Prisoner of Azkaban"],"name":"J. K. Rowling","numberOfBooks":22}


Десериализация на Java выглядит примерно так:

JSONObject author = new JSONObject(serializedString);
System.out.println("name: " + author.get("name"));
System.out.println("numberOfBooks: " + author.get("numberOfBooks"));

JSONArray books = (JSONArray) author.get("books");
Iterator<Object> i = books.iterator();
System.out.println("books:");
while (i.hasNext()) {
System.out.println(i.next());
}


Нужно добавить зависимость:

<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20231013</version>
</dependency>
👍16🔥64
Array vs ArrayList

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

📌Помните о следующих особенностях этих типов:

• Array имеет фиксированный размер и память для него выделяется в момент объявления, а размер ArrayLists может динамически изменяться.

• Массивы Java работают гораздо быстрее, а в ArrayList намного проще добавлять/удалять элементы.

• При работе с Array велика вероятность получить ошибку ArrayIndexOutOfBoundsException.

• У ArrayList только одно измерение, а вот массивы Java могут быть многомерными.

import java.util.ArrayList;

public class arrayVsArrayList {

public static void main(String[] args) {

// объявление Array
int[] myArray = new int[6];

// обращение к несуществующему индексу
myArray[7]= 10; // ArrayIndexOutOfBoundsException

// объявление ArrayList
ArrayList<Integer> myArrayList = new ArrayList<>();

// простое добавление и удаление элементов
myArrayList.add(1);
myArrayList.add(2);
myArrayList.add(3);
myArrayList.add(4);
myArrayList.add(5);
myArrayList.remove(0);

// получение элементов ArrayList
for(int i = 0; i < myArrayList.size(); i++) {
System.out.println("Element: " + myArrayList.get(i));
}

// многомерный Array
int[][][] multiArray = new int [3][3][3];
}
}
👍161👎1🔥1🤗1
⌨️ Фишка: Создание итератора для пользовательского класса.

Код:
import java.util.Iterator;

public class CustomClass implements Iterable<String> {
private String[] elements;

public CustomClass(String[] elements) {
this.elements = elements;
}

@Override
public Iterator<String> iterator() {
return new CustomIterator();
}

private class CustomIterator implements Iterator<String> {
private int index = 0;

@Override
public boolean hasNext() {
return index < elements.length;
}

@Override
public String next() {
if (this.hasNext()) {
return elements[index++];
} else {
throw new NoSuchElementException();
}
}
}

public static void main(String[] args) {
String[] arr = {"one", "two", "three"};
CustomClass customClass = new CustomClass(arr);

for (String element : customClass) {
System.out.println(element);
}
}
}


💁‍♂️ Этот код позволяет создать итератор для пользовательского класса CustomClass. Итератор позволяет перебирать элементы массива elements и использовать их в цикле for-each.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍122🔥1🤝1
⌨️ Использование интерфейсов для множественного наследования

// Создание интерфейсов
interface Printable {
void print();
}

interface Showable {
void show();
}

// Реализация интерфейсов в классе
class MyClass implements Printable, Showable {
public void print() {
System.out.println("Printing...");
}

public void show() {
System.out.println("Showing...");
}
}

public class Main {
public static void main(String[] args) {
// Создание объекта класса MyClass
MyClass obj = new MyClass();
obj.print();
obj.show();
}
}


🔎 В данном коде используются интерфейсы для реализации множественного наследования. Класс MyClass реализует два интерфейса Printable и Showable, и поэтому класс может использовать методы, определенные в обоих интерфейсах. Это позволяет создавать гибкие и модульные программы, используя механизм интерфейсов в Java.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥4👨‍💻21
⌨️ Использование StringBuilder для эффективной конкатенации строк:

public class StringBuilderExample {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
sb.append("строка ").append(i).append("\n");
}
String result = sb.toString();
System.out.println(result);
}
}


📌 В этом примере используется StringBuilder для объединения 10 строк "строка i" в одну строку. Это более эффективно, чем использование оператора "+" или String.concat(), особенно при большом количестве операций конкатенации строк.

StringBuilder предоставляет изменяемую последовательность символов и позволяет выполнять эффективные операции вставки, удаления и конкатенации строк.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥31
💻 Как полезную фишку на Java можно рассмотреть использование лямбда-выражений для упрощения написания анонимных классов. Например, использование лямбда-выражения для выполнения операции над элементами коллекции:

import java.util.Arrays;
import java.util.List;

public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// Использование лямбда-выражения для вывода каждого элемента в консоль
numbers.forEach(n -> System.out.println(n));

// Использование лямбда-выражения для умножения каждого элемента на 2
numbers.replaceAll(n -> n * 2);
System.out.println(numbers); // Вывод: [2, 4, 6, 8, 10]
}
}


🔝 Использование лямбда-выражений делает код более компактным и удобочитаемым, особенно при работе с коллекциями и функциональными интерфейсами.
👍17🔥42🥰2
⌨️ Параллельное выполнение задач с использованием ExecutorService

ExecutorService - это интерфейс, который предоставляет удобный способ для управления параллельным выполнением задач. Он предоставляет пул потоков для выполнения задач и управляет их жизненным циклом:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
public static void main(String[] args) {
// Создание пула потоков
ExecutorService executor = Executors.newFixedThreadPool(5);

// Подача задач на выполнение
for (int i = 0; i < 10; i++) {
executor.execute(new Task(i));
}

// Остановка пула потоков после выполнения задач
executor.shutdown();
}

static class Task implements Runnable {
private int taskId;

public Task(int taskId) {
this.taskId = taskId;
}

@Override
public void run() {
System.out.println("Выполнение задачи " + taskId + " в потоке " +
Thread.currentThread().getName());
}
}
}


🧑‍💻Этот код создает пул из 5 потоков и подает на выполнение 10 задач. Каждая задача выводит свой идентификатор и имя потока, в котором она выполняется. После выполнения всех задач пул потоков останавливается.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥53👨‍💻1
Did anyone say Java?
👍42🤣7🔥5😁3🤩2💯21
⌨️ Использование интерфейса Callable вместе с классом Future для выполнения асинхронных задач и получения их результата:

ExecutorService executor = null;
try {
executor = Executors.newFixedThreadPool(1);
Future<Integer> futureResult = executor.submit(() -> {
// Выполнение сложной вычислительной задачи
int result = 0;
for (int i = 0; i < 100; i++) {
result += i;
Thread.sleep(100);
}
return result;
});

// Другие действия, выполняемые параллельно

// Ожидание завершения асинхронной задачи и получение результата
Integer result = futureResult.get();
System.out.println("Результат: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
if (executor != null) executor.shutdown();
}

➡️В данном примере создается пул потоков размером 1, затем создается асинхронная задача с использованием интерфейса Callable, который возвращает результат типа Integer. Задача выполняет сложное вычисление с задержкой в 100 миллисекунд каждую итерацию.

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

Метод get() вызывается для ожидания завершения задачи и получения результата. Если задача еще не завершилась, вызов этого метода блокируется. Возможны исключения, такие как InterruptedException или ExecutionException, которые необходимо обработать.

💁‍♂️ Затем поток пул завершается вызовом shutdown().
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10👨‍💻32🔥1💯1
⌨️ Метод для глубокого копирования объектов. Это часто используется, когда нужно создать копию объекта, сохраняя его данные, но не связи с другими объектами.

📌 Вот пример метода для глубокого копирования:

import java.io.*;

public class DeepCopyExample {
public static void main(String[] args) {
Person person = new Person("John", 30);
Person deepCopy = deepCopy(person);

System.out.println("Original: " + person.getName() + ", " + person.getAge());
System.out.println("Deep copy: " + deepCopy.getName() + ", " + deepCopy.getAge());
}

public static <T extends Serializable> T deepCopy(T object) {
try {
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream);
objectOutputStream.writeObject(object);

ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteOutputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteInputStream);
T copy = (T) objectInputStream.readObject();

return copy;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
}

class Person implements Serializable {
private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}
}


В этом примере мы создаем класс Person, который реализует интерфейс Serializable, чтобы объекты этого класса можно было сериализовать и десериализовать. Затем мы создаем метод deepCopy, который принимает объект и возвращает его глубокую копию.

Мы используем ByteArrayOutputStream и ObjectOutputStream, чтобы записать объект в байтовый массив, а затем ByteArrayInputStream и ObjectInputStream, чтобы прочитать копию объекта из массива.

В методе main мы создаем объект Person, затем создаем его глубокую копию с помощью метода deepCopy и выводим на экран значения оригинального и скопированного объекта.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍93🔥2👏1💯1👨‍💻1
⌨️ Использования анонимных классов:

Анонимный класс - это класс без имени, который объявляется и создается внутри другого класса или метода. Он удобен, когда требуется определить класс, который будет использоваться только один раз, и нет необходимости создавать отдельный класс.

public class Main {
interface Greeting {
void sayHello();
}

public static void main(String[] args) {
Greeting greeting = new Greeting() { // объявление и создание анонимного класса
@Override
public void sayHello() {
System.out.println("Привет, мир!");
}
};

greeting.sayHello(); // вызов метода sayHello у анонимного класса
}
}


В данном примере мы определили интерфейс Greeting, содержащий метод sayHello(). Затем, в методе main(), мы создали анонимный класс, реализующий интерфейс Greeting и переопределивший метод sayHello(). Затем мы вызываем метод sayHello() у объекта анонимного класса.

📝Таким образом, анонимные классы предоставляют удобный способ создания и использования классов "на лету", что может быть полезно, когда требуется определить классы, которые будут использоваться только в одном месте программы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍84🔥3👏1
⌨️ Работа с коллекциями элементарных типов данных благодаря классам-оболочкам (Wrapper Classes)


import java.util.ArrayList;
import java.util.List;

public class WrapperExample {
public static void main(String[] args) {
// Создание списка оберток для целых чисел
List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);

// Использование методов класса-оболочки
int sum = 0;
for (int i = 0; i < numbers.size(); i++) {
sum += numbers.get(i);
}
System.out.println("Сумма чисел: " + sum);
}
}


В этом примере создается список оберток numbers для целых чисел типа Integer. Затем мы добавляем в список несколько элементов и используем метод get() для получения элементов из списка. Значения оберток автоматически анбоксируются в примитивные типы данных int, и мы можем выполнять с ними операции, например, суммирование.
Использование классов-оболочек позволяет работать с коллекциями элементарных типов данных и обеспечивает удобство и безопасность при работе с ними.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥112👍2👏1
⌨️ Обработка исключений с помощью Try-With-Resources.

Try-With-Resources - это новая конструкция языка, введенная в Java 7, которая облегчает работу с ресурсами такими как файлы или сокеты и сокращает количество кода, необходимого для обработки исключений.

Вот пример использования Try-With-Resources для чтения содержимого файла:

try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}


💻В этом примере мы открываем BufferedReader внутри блока try с помощью конструктора FileReader. Затем мы можем безопасно читать файл внутри этого блока без необходимости явно закрывать ресурс.

После завершения блока try автоматически вызывается метод close() объекта reader, который закрывает файл и освобождает связанные с ним ресурсы. Если возникнет исключение в блоке try, его можно будет обработать в блоке catch после завершения работы с ресурсом.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥3👏2🥰1
🤣35😁6🤯4💯3👍1
⌨️ Использование CompletableFuture для асинхронных операций.

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

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class CompletableFutureExample {
public static void main(String[] args) {
// Создание CompletableFuture объекта
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");

// Добавление операций после выполнения асинхронной задачи
CompletableFuture<String> result = future.thenApplyAsync(str -> str + " World")
.thenApply(str -> str + "!");

try {
// Ожидание результата
String message = result.get();
System.out.println(message);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}


🧑‍💻В данном примере мы создаем CompletableFuture объект future, который возвращает строку "Hello". Затем мы добавляем операции thenApplyAsync и thenApply, которые обрабатывают результат асинхронной задачи и добавляют к нему слова "World" и "!", соответственно.

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

💁‍♂️ Таким образом, использование CompletableFuture позволяет нам эффективно работать с асинхронными задачами и упрощает обработку результатов. Это может быть особенно полезно в многопоточном или параллельном программировании.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9👨‍💻31
⌨️ Использование Stream API для работы с коллекциями данных.

import java.util.Arrays;
import java.util.List;

public class StreamExample {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");

// Фильтрация элементов, начинающихся с буквы "a" и преобразование в верхний регистр
fruits.stream()
.filter(fruit -> fruit.startsWith("a"))
.map(String::toUpperCase)
.forEach(System.out::println);
// Выведет "APPLE"
}
}


📝 В этом примере мы использовали Stream API для фильтрации элементов коллекции, начинающихся с буквы "a", и преобразования их в верхний регистр, а затем вывели результат в консоль. Stream API предоставляет мощный и удобный способ работы с коллекциями данных в Java, позволяя выполнять различные операции, такие как фильтрация, отображение, сортировка, агрегация и многое другое.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥4👏21
⌨️ Код для реализации уникального идентификатора (UUID):

import java.util.UUID;

public class UniqueIdGenerator {

public static void main(String[] args) {
// Генерация случайного уникального идентификатора
UUID uuid = UUID.randomUUID();
System.out.println("Уникальный идентификатор: " + uuid);

// Преобразование уникального идентификатора в строку без тире
String uuidString = uuid.toString().replace("-", "");
System.out.println("Уникальный идентификатор без тире: " + uuidString);
}


Этот код генерирует случайный уникальный идентификатор (UUID) и выводит его значение в формате с и без использования тире. Уникальный идентификатор предоставляет уникальное значение, которое может быть использовано для идентификации объектов, сессий, операций и т. д.

Это полезно, например, при создании уникального идентификатора для записи в базу данных или для генерации уникального имени файла.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍111🥰1👏1