Java for Beginner
677 subscribers
546 photos
155 videos
12 files
836 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Основные методы классов Date, Calendar и java.time, примеры применения

Основные методы класса Date

getTime()
Метод getTime() возвращает количество миллисекунд, прошедших с 1 января 1970 года. Это значение полезно для хранения времени в числовом формате или для сравнения дат.
import java.util.Date;

public class DateMethodsExample {
public static void main(String[] args) {
Date date = new Date();
long time = date.getTime();
System.out.println("Milliseconds since January 1, 1970: " + time);
}
}


after() и before()
Эти методы позволяют сравнивать две даты. Метод after() возвращает true, если текущая дата позже указанной, а before() — если раньше.
import java.util.Date;

public class DateComparisonExample {
public static void main(String[] args) {
Date date1 = new Date();
Date date2 = new Date(date1.getTime() + 10000); // 10 секунд позже

System.out.println("Is date1 before date2? " + date1.before(date2)); // true
System.out.println("Is date1 after date2? " + date1.after(date2)); // false
}
}


toString()
Метод toString() возвращает строковое представление даты. Этот метод полезен для быстрой отладки или вывода даты в формате по умолчанию.
import java.util.Dateimport java.util.Date;

public class DateToStringExample {
public static void main(String[] args) {
Date date = new Date();
System.out.println("Current Date: " + date.toString());
}
}
Этот пример показывает, как можно вывести дату в виде строки.


Основные методы класса Calendar

getInstance()
Метод getInstance() создает и возвращает объект Calendar, настроенный на текущую дату и время по умолчанию. Этот метод используется для получения базового объекта Calendar, с которым можно работать.
import java.util.Calendar;

public class CalendarGetInstanceExample {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
System.out.println("Current Date and Time: " + calendar.getTime());
}
}


set()
Метод set() позволяет устанавливать дату и время в объекте Calendar. Этот метод полезен, когда нужно работать с конкретной датой или временем.
import java.util.Calendar;

public class CalendarSetExample {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(2021, Calendar.OCTOBER, 1);
System.out.println("Specific Date: " + calendar.getTime());
}
}


add()
Метод add() позволяет изменять дату и время путем добавления или вычитания определенного количества дней, месяцев или лет.

import java.util.Calendar;

public class CalendarAddExample {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, 5);
System.out.println("Date after adding 5 days: " + calendar.getTime());
}
}
Этот пример показывает, как добавить 5 дней к текущей дате.


get()
Метод get() позволяет получить значение конкретного поля даты, например, год, месяц, день или час.
import java.util.Calendar;

public class CalendarGetExample {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1; // месяцы начинаются с 0
int day = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println("Year: " + year + ", Month: " + month + ", Day: " + day);
}
}


#Java #Training #Medium #Date #Calendar #Time
Основные методы java.time API

now()
Метод now() доступен в большинстве классов java.time (например, LocalDate, LocalTime, LocalDateTime) и используется для получения текущей даты, времени или их комбинации.
import java.time.LocalDate;
import java.time.LocalDateTime;

public class DateTimeNowExample {
public static void main(String[] args) {
LocalDate currentDate = LocalDate.now();
LocalDateTime currentDateTime = LocalDateTime.now();
System.out.println("Current Date: " + currentDate);
System.out.println("Current Date and Time: " + currentDateTime);
}
}


of()

Метод of() используется для создания объекта LocalDate, LocalTime или LocalDateTime с заданными значениями даты и/или времени.
import java.time.LocalDate;

public class DateTimeOfExample {
public static void main(String[] args) {
LocalDate specificDate = LocalDate.of(2021, 10, 1);
System.out.println("Specific Date: " + specificDate);
}
}


plusDays(), minusDays() и другие аналогичные методы
Эти методы позволяют добавлять или вычитать дни, месяцы, годы и другие временные единицы из объекта LocalDate или LocalDateTime.
import java.time.LocalDate;

public class DateTimePlusMinusExample {
public static void main(String[] args) {
LocalDate currentDate = LocalDate.now();
LocalDate dateAfterAddingDays = currentDate.plusDays(5);
LocalDate dateAfterSubtractingMonths = currentDate.minusMonths(2);
System.out.println("Date after adding 5 days: " + dateAfterAddingDays);
System.out.println("Date after subtracting 2 months: " + dateAfterSubtractingMonths);
}
}


parse()
Метод parse() позволяет создавать объекты LocalDate, LocalTime, LocalDateTime из строковых представлений даты или времени.
import java.time.LocalDate;

public class DateTimeParseExample {
public static void main(String[] args) {
String dateString = "2023-08-28";
LocalDate date = LocalDate.parse(dateString);
System.out.println("Parsed Date: " + date);
}
}


format()
Метод format() используется для преобразования объекта LocalDate, LocalTime, LocalDateTime в строку с использованием определенного формата.
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class DateTimeFormatExample {
public static void main(String[] args) {
LocalDate date = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String formattedDate = date.format(formatter);
System.out.println("Formatted Date: " + formattedDate);
}
}


#Java #Training #Medium #Date #Calendar #Time
Класс Random в Java. Особенности и внутреннее устройство

Генерация случайных чисел — одна из важных задач в программировании, которая находит применение в самых разных областях, начиная от криптографии и заканчивая играми. В Java для этой цели существует класс Random, который позволяет создавать последовательности псевдослучайных чисел.


Основы работы класса Random

Класс Random в Java предоставляет средства для генерации случайных чисел различного типа: целых чисел, чисел с плавающей точкой, булевых значений и т. д. Этот класс базируется на генераторе псевдослучайных чисел (PRNG, pseudo-random number generator), который использует начальное значение (seed) для создания предсказуемой последовательности чисел, которая выглядит случайной.

Когда создается объект Random без указания начального значения, используется текущее время системы в миллисекундах в качестве seed, что делает каждую последовательность уникальной для каждого запуска программы.
import java.util.Random;

public class RandomExample {
public static void main(String[] args) {
Random random = new Random();
int randomInt = random.nextInt();
System.out.println("Random Integer: " + randomInt);
}
}
Этот код создает объект Random и генерирует случайное целое число.


Внутреннее устройство класса Random

Класс Random реализует линейный конгруэнтный метод (LCG) для генерации псевдослучайных чисел. Этот метод заключается в следующем:

𝑋𝑛+1=(𝑎⋅𝑋𝑛+𝑐) mod  𝑚
где:
Xn — текущее значение (seed).
𝑎 — множитель (multiplier).
𝑐 — приращение (increment).
𝑚 — модуль (modulus).


В Java, значения для a, c и m подобраны таким образом, чтобы генератор обладал хорошими статистическими свойствами и большой длиной периода. На практике это означает, что последовательность чисел, сгенерированных объектом Random, будет выглядеть случайной, хотя на самом деле она полностью детерминирована и повторяема при одинаковом начальном значении.

Пример создания объекта Random с seed:
import java.util.Random;

public class RandomWithSeedExample {
public static void main(String[] args) {
Random random = new Random(42); // Создаем Random с фиксированным seed
int randomInt1 = random.nextInt();
int randomInt2 = random.nextInt();

System.out.println("Random Integer 1: " + randomInt1);
System.out.println("Random Integer 2: " + randomInt2);
}
}
В этом примере при каждом запуске программы будут генерироваться одни и те же числа, так как seed фиксирован.


#Java #Training #Medium #Random
Особенности класса Random

Детерминированность: Класс Random генерирует последовательности чисел, которые можно воспроизвести, если известно начальное значение (seed). Это полезно, например, для тестирования, когда нужно получать одни и те же результаты на каждом запуске программы.
Многопоточность: Random не является потокобезопасным. При использовании в многопоточной среде возможны конфликты, приводящие к некорректной работе. Для таких случаев лучше использовать ThreadLocalRandom, который оптимизирован для многопоточных приложений.
Период генератора: Период генератора — это максимальная длина последовательности псевдослучайных чисел, прежде чем она начнет повторяться. У Random достаточно большой период, чтобы его было сложно заметить в реальных приложениях, однако, он все равно существует.


Альтернативы: Существует несколько альтернатив классу Random, такие как SecureRandom, который обеспечивает более высокую степень случайности, и SplittableRandom, который эффективнее в многопоточных сценариях.

Влияние начального значения (seed)

Одной из ключевых особенностей работы с Random является возможность задания начального значения (seed). Понимание этой концепции важно для ситуаций, когда требуется воспроизводимость экспериментов или процессов.

Фиксированный seed: Если используется фиксированный seed, последовательность случайных чисел всегда будет одинаковой. Это полезно для тестирования, где результаты должны быть предсказуемыми и сравнимыми.
Случайный seed: Когда seed не задан явно, используется текущее время в миллисекундах. Это обеспечивает разнообразие последовательностей чисел при каждом запуске программы, но делает воспроизводимость невозможной без логирования seed.

import java.util.Random;

public class RandomSeedExample {
public static void main(String[] args) {
Random random1 = new Random(12345);
Random random2 = new Random(12345);

System.out.println("Random 1:");
System.out.println(random1.nextInt());
System.out.println(random1.nextInt());

System.out.println("Random 2:");
System.out.println(random2.nextInt());
System.out.println(random2.nextInt());
}
}
В этом примере оба объекта Random генерируют одинаковые числа, так как они используют один и тот же seed.


Недостатки и ограничения

Несмотря на широкое применение, класс Random имеет некоторые ограничения:
Псевдослучайность: Генератор не создает истинно случайных чисел. Для криптографии и других задач, требующих высокой степени случайности, лучше использовать SecureRandom.
Неоптимальность в многопоточности: Random не оптимизирован для использования в многопоточных приложениях. Если несколько потоков одновременно используют один и тот же объект Random, это может привести к снижению производительности и даже к ошибкам.
Ограниченная функциональность: Random не предоставляет методов для генерации всех возможных распределений случайных чисел (например, нормального распределения). Для этих целей потребуется использовать дополнительные библиотеки или писать собственную реализацию.


#Java #Training #Medium #Random
Что выведет код?

import java.util.Random;

public class Main {
public static void main(String[] args) {
Random random = new Random(12345);
int value1 = random.nextInt(10);
int value2 = random.nextInt(10);
int value3 = random.nextInt(10);
System.out.println(value1 + ", " + value2 + ", " + value3);
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
25%
2, 5, 7
50%
5, 2, 8
13%
1, 0, 1
13%
1, 0, 0
Новый челлендж - посчитайте Вашу энергию за сегодня!!!😉😂🤪

https://t.me/Java_for_beginner_dev

#Mems
Основные методы класса Random, примеры применения

nextInt()
Этот метод генерирует случайное целое число в пределах от Integer.MIN_VALUE до Integer.MAX_VALUE. Он часто используется в различных приложениях, где необходимо случайным образом выбирать индекс массива или генерировать идентификаторы.
import java.util.Random;

public class NextIntExample {
public static void main(String[] args) {
Random random = new Random();
int randomInt = random.nextInt();
System.out.println("Random Integer: " + randomInt);
}
}


nextInt(int bound)
Этот метод возвращает случайное целое число в диапазоне от 0 (включительно) до указанного значения bound (исключительно). Это полезно для выбора случайного элемента из массива или списка фиксированного размера.
import java.util.Random;

public class NextIntBoundExample {
public static void main(String[] args) {
Random random = new Random();
int randomInt = random.nextInt(10); // Генерация числа от 0 до 9
System.out.println("Random Integer (0-9): " + randomInt);
}
}


nextLong()
Метод nextLong() генерирует случайное длинное целое число (тип long) в пределах от Long.MIN_VALUE до Long.MAX_VALUE.
import java.util.Random;

public class NextLongExample {
public static void main(String[] args) {
Random random = new Random();
long randomLong = random.nextLong();
System.out.println("Random Long: " + randomLong);
}
}


nextFloat()
Этот метод возвращает случайное число с плавающей точкой типа float в диапазоне от 0.0 до 1.0 (исключительно). Применяется в ситуациях, когда требуется получить случайное дробное число в пределах фиксированного диапазона.
import java.util.Random;

public class NextFloatExample {
public static void main(String[] args) {
Random random = new Random();
float randomFloat = random.nextFloat();
System.out.println("Random Float: " + randomFloat);
}
}


nextDouble()
Метод nextDouble() аналогичен nextFloat(), но возвращает значение типа double. Он используется для генерации случайных дробных чисел с большей точностью.
import java.util.Random;

public class NextDoubleExample {
public static void main(String[] args) {
Random random = new Random();
double randomDouble = random.nextDouble();
System.out.println("Random Double: " + randomDouble);
}
}


nextBoolean()
Метод nextBoolean() генерирует случайное логическое значение (true или false). Этот метод полезен в ситуациях, когда необходимо принять случайное бинарное решение, например, выбор направления или вариант действия.
import java.util.Random;

public class NextBooleanExample {
public static void main(String[] args) {
Random random = new Random();
boolean randomBoolean = random.nextBoolean();
System.out.println("Random Boolean: " + randomBoolean);
}
}


nextBytes(byte[] bytes)
Метод nextBytes(byte[] bytes) заполняет переданный массив байтов случайными значениями. Это полезно, когда нужно сгенерировать массив случайных байтов, например, для использования в криптографических алгоритмах или для случайной инициализации данных.
import java.util.Random;

public class NextBytesExample {
public static void main(String[] args) {
Random random = new Random();
byte[] randomBytes = new byte[10];
random.nextBytes(randomBytes);

System.out.println("Random Bytes: ");
for (byte b : randomBytes) {
System.out.print(b + " ");
}
}
}


#Java #Training #Medium #Random
Примеры применения методов класса Random

1. Симуляция броска кубика

Представим, что нужно создать программу, которая будет симулировать бросок кубика. Это классическая задача, где необходимо сгенерировать случайное число от 1 до 6.
import java.util.Random;

public class DiceRollSimulation {
public static void main(String[] args) {
Random random = new Random();
int diceRoll = random.nextInt(6) + 1; // Генерация числа от 1 до 6
System.out.println("Dice Roll: " + diceRoll);
}
}
В этом примере мы используем метод nextInt(int bound) с параметром 6, чтобы получить случайное число от 0 до 5, и добавляем 1, чтобы результат был в диапазоне от 1 до 6.


2. Генерация случайного пароля
Допустим, нам нужно сгенерировать случайный пароль длиной 8 символов, состоящий из букв и цифр. Мы можем использовать методы класса Random для этой задачи.
import java.util.Random;

public class PasswordGenerator {
public static void main(String[] args) {
Random random = new Random();
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder password = new StringBuilder();

for (int i = 0; i < 8; i++) {
int index = random.nextInt(characters.length());
password.append(characters.charAt(index));
}

System.out.println("Generated Password: " + password.toString());
}
}
Этот код создает случайный пароль длиной 8 символов, используя метод nextInt(int bound) для выбора случайного индекса символа из строки, содержащей все возможные символы пароля.


3. Симуляция монетки
Если вам нужно смоделировать подбрасывание монетки (где есть только два возможных исхода — орел или решка), можно использовать метод nextBoolean().
import java.util.Random;

public class CoinFlipSimulation {
public static void main(String[] args) {
Random random = new Random();
boolean coinFlip = random.nextBoolean();
if (coinFlip) {
System.out.println("Heads");
} else {
System.out.println("Tails");
}
}
}
В этом примере случайное значение true означает "Орел", а false — "Решка".


4. Случайный выбор из списка
Представьте, что вам нужно случайным образом выбрать элемент из списка, например, случайное имя из списка имен.
import java.util.Random;
import java.util.List;
import java.util.Arrays;

public class RandomNamePicker {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Diana");
Random random = new Random();
String randomName = names.get(random.nextInt(names.size()));

System.out.println("Randomly Picked Name: " + randomName);
}
}
Здесь метод nextInt(int bound) используется для выбора случайного индекса из списка имен.


5. Генерация случайной даты
Если вам нужно сгенерировать случайную дату в определенном диапазоне, можно воспользоваться комбинацией Random и Calendar.
import java.util.Random;
import java.util.Calendar;

public class RandomDateGenerator {
public static void main(String[] args) {
Random random = new Random();
Calendar calendar = Calendar.getInstance();

int year = random.nextInt(2022 - 2000) + 2000; // Год от 2000 до 2021
int dayOfYear = random.nextInt(calendar.getActualMaximum(Calendar.DAY_OF_YEAR)) + 1;

calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.DAY_OF_YEAR, dayOfYear);

System.out.println("Random Date: " + calendar.getTime());
}
}
В этом примере мы генерируем случайную дату между 2000 и 2021 годами, используя случайное число для года и дня года.


#Java #Training #Medium #Random
Рекурсия в Java.

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

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

Базовый случай: Это условие, при котором рекурсия прекращается. Базовый случай определяет, когда функция должна перестать вызывать себя и просто вернуть результат.
Рекурсивный случай: Это часть функции, где она вызывает саму себя для решения меньшей версии задачи.


Рекурсия особенно полезна для задач, которые могут быть естественно разделены на несколько подзадач того же типа, как например задачи на обход дерева, решение задач на комбинаторику, задачи на нахождение факториала, чисел Фибоначчи и так далее.

Пример простой рекурсивной функции — вычисление факториала:

public class FactorialExample {
public static int factorial(int n) {
if (n == 0) {
return 1; // Базовый случай
} else {
return n * factorial(n - 1); // Рекурсивный случай
}
}

public static void main(String[] args) {
int result = factorial(5);
System.out.println("Factorial of 5 is: " + result);
}
}
В этом примере функция factorial вызывает саму себя, пока не достигнет базового случая, когда n равно 0.


Виды рекурсии

Прямая рекурсия (Direct Recursion)

В прямой рекурсии функция напрямую вызывает саму себя. Это самый простой и распространенный вид рекурсии.
public class DirectRecursionExample {
public static void countdown(int n) {
if (n == 0) {
System.out.println("Done!");
} else {
System.out.println(n);
countdown(n - 1); // Прямой рекурсивный вызов
}
}

public static void main(String[] args) {
countdown(5);
}
}


Косвенная рекурсия (Indirect Recursion)

В косвенной рекурсии функция A вызывает функцию B, которая в свою очередь вызывает функцию A. Этот процесс может быть продолжен с участием нескольких функций, которые вызывают друг друга.
public class IndirectRecursionExample {
public static void functionA(int n) {
if (n > 0) {
System.out.println("A: " + n);
functionB(n - 1);
}
}

public static void functionB(int n) {
if (n > 0) {
System.out.println("B: " + n);
functionA(n - 1);
}
}

public static void main(String[] args) {
functionA(5);
}
}


Хвостовая рекурсия (Tail Recursion)

Хвостовая рекурсия — это особый вид рекурсии, когда рекурсивный вызов является последним действием в функции. В хвостовой рекурсии результат рекурсивного вызова сразу возвращается без дополнительных операций. Это позволяет компиляторам оптимизировать работу, избегая создания нового стека вызовов для каждой рекурсии.
public class TailRecursionExample {
public static int tailFactorial(int n, int acc) {
if (n == 0) {
return acc;
} else {
return tailFactorial(n - 1, n * acc); // Хвостовой рекурсивный вызов
}
}

public static void main(String[] args) {
int result = tailFactorial(5, 1);
System.out.println("Factorial of 5 is: " + result);
}
}
В этом примере хвостовая рекурсия позволяет эффективно вычислить факториал без необходимости удерживать промежуточные результаты в стеке вызовов.


#Java #Training #Medium #Recursion
Нерегулярная рекурсия (Non-Regular Recursion)

Нерегулярная рекурсия используется в случаях, когда количество рекурсивных вызовов не фиксировано. Она часто используется для обхода графов, деревьев и других структур данных.
public class TreeNode {
int value;
TreeNode left, right;

TreeNode(int value) {
this.value = value;
left = right = null;
}
}

public class TreeTraversal {
public static void inOrder(TreeNode node) {
if (node != null) {
inOrder(node.left); // Рекурсивный вызов для левого поддерева
System.out.println(node.value);
inOrder(node.right); // Рекурсивный вызов для правого поддерева
}
}

public static void main(String[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);

inOrder(root);
}
}
В этом примере используется нерегулярная рекурсия для обхода бинарного дерева в порядке in-order.


Внутреннее устройство рекурсии


Рекурсия в Java и других языках программирования основывается на стеке вызовов. Когда функция вызывает саму себя, текущее состояние функции (значения переменных, адрес возврата и т.д.) сохраняется в стеке вызовов. После завершения рекурсивного вызова управление возвращается к предыдущему состоянию.

Стек вызовов — это структура данных, работающая по принципу "последним пришел — первым вышел" (LIFO). Каждый рекурсивный вызов добавляет новый фрейм в стек, который содержит информацию о текущем состоянии функции. После завершения рекурсивного вызова этот фрейм удаляется из стека, и программа возвращается к предыдущему вызову.


Пример работы стека вызовов на примере вычисления факториала числа 3.
factorial(3)
-> 3 * factorial(2)
-> 2 * factorial(1)
-> 1 * factorial(0)
-> return 1
-> return 1 * 1 = 1
-> return 2 * 1 = 2
-> return 3 * 2 = 6
На каждом этапе рекурсивного вызова в стек добавляется новый фрейм. Когда функция достигает базового случая (factorial(0)), она начинает возвращаться, удаляя фреймы из стека и комбинируя результаты.


Преимущества и недостатки рекурсии

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


Недостатки:
Риск переполнения стека: Если глубина рекурсии слишком велика, это может привести к переполнению стека вызовов и завершению программы с ошибкой StackOverflowError.
Затраты на память и производительность: Каждый рекурсивный вызов требует дополнительной памяти для хранения состояния в стеке, что может негативно сказаться на производительности программы.
Сложность отладки: Рекурсивные программы сложнее отлаживать из-за необходимости отслеживания множества уровней вызовов.


#Java #Training #Medium #Recursion
Варианты ответа:
Anonymous Quiz
7%
2
29%
4
14%
12
50%
24
Что выведет код?

public class Main {
public static void main(String[] args) {
System.out.println(factorial(4));
}

public static int factorial(int n) {
if (n <= 1) {
return 1;
} else {
return n * factorial(n - 1);
}
}
}


#Tasks
А какой нравится Вам?😂🤦‍♂️🤪

https://t.me/Java_for_beginner_dev

#Mems
Примеры использования рекурсии в Java.

1. Вычисление чисел Фибоначчи

Одним из классических примеров рекурсии является вычисление чисел Фибоначчи. Последовательность Фибоначчи определяется следующим образом:
F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2) для n > 1


Пример реализации:
public class FibonacciExample {
public static int fibonacci(int n) {
if (n == 0) {
return 0; // Базовый случай
} else if (n == 1) {
return 1; // Базовый случай
} else {
return fibonacci(n - 1) + fibonacci(n - 2); // Рекурсивный случай
}
}

public static void main(String[] args) {
int n = 10;
System.out.println("Fibonacci of " + n + " is: " + fibonacci(n));
}
}
Этот код вычисляет 10-е число Фибоначчи. Однако, такой подход неэффективен для больших значений n, так как происходит многократное вычисление одних и тех же значений. В таких случаях лучше использовать динамическое программирование или итеративные решения.


2. Обратная строка

Рекурсия может быть использована для выполнения операций на строках. Например, мы можем создать функцию, которая будет возвращать обратную строку, используя рекурсию.
public class ReverseStringExample {
public static String reverse(String str) {
if (str.isEmpty()) {
return str; // Базовый случай
}
return reverse(str.substring(1)) + str.charAt(0); // Рекурсивный случай
}

public static void main(String[] args) {
String original = "hello";
String reversed = reverse(original);
System.out.println("Original: " + original);
System.out.println("Reversed: " + reversed);
}
}
Этот код переворачивает строку "hello" и выводит "olleh". Рекурсивная функция reverse удаляет первый символ строки и добавляет его в конец результата рекурсивного вызова.


3. Поиск максимального элемента в массиве

Еще один пример применения рекурсии — поиск максимального элемента в массиве. Для этого мы можем рекурсивно сравнивать элементы массива, пока не найдем максимальный.
public class MaxElementExample {
public static int findMax(int[] arr, int n) {
if (n == 1) {
return arr[0]; // Базовый случай: один элемент
}
return Math.max(arr[n - 1], findMax(arr, n - 1)); // Рекурсивный случай
}

public static void main(String[] args) {
int[] array = {1, 5, 3, 9, 2};
int max = findMax(array, array.length);
System.out.println("Maximum element is: " + max);
}
}
Этот код ищет максимальный элемент в массиве [1, 5, 3, 9, 2], и выводит 9.


4. Обход директории
Рекурсия также может быть использована для обхода файловой системы. Например, для поиска файлов в директории и всех её поддиректориях.
import java.io.File;

public class DirectoryTraversalExample {
public static void listFiles(File dir) {
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
listFiles(file); // Рекурсивный случай: обход поддиректории
} else {
System.out.println("File: " + file.getAbsolutePath());
}
}
}
}

public static void main(String[] args) {
File dir = new File("/path/to/directory");
listFiles(dir);
}
}
Этот код рекурсивно обходит директорию и все её поддиректории, выводя полные пути к файлам.


#Java #Training #Medium #Recursion
5. Разрешение головоломок
Рекурсия часто используется в решении задач и головоломок, таких как задача о восьми ферзях, судоку и другие. Например, рассмотрим задачу о Ханойской башне.

Пример реализации Ханойской башни:
public class TowerOfHanoiExample {
public static void solveHanoi(int n, char fromRod, char toRod, char auxRod) {
if (n == 1) {
System.out.println("Move disk 1 from rod " + fromRod + " to rod " + toRod);
return;
}
solveHanoi(n - 1, fromRod, auxRod, toRod);
System.out.println("Move disk " + n + " from rod " + fromRod + " to rod " + toRod);
solveHanoi(n - 1, auxRod, toRod, fromRod);
}

public static void main(String[] args) {
int n = 3; // Количество дисков
solveHanoi(n, 'A', 'C', 'B'); // A, B и C - названия стержней
}
}
Этот код решает задачу о Ханойской башне для трех дисков. Рекурсивная функция перемещает диски между стержнями согласно правилам задачи.


6. Генерация всех перестановок строки

Рекурсия может быть использована для генерации всех возможных перестановок символов строки. Этот алгоритм полезен в задачах комбинаторики.
public class PermutationsExample {
public static void permute(String str, int l, int r) {
if (l == r) {
System.out.println(str);
} else {
for (int i = l; i <= r; i++) {
str = swap(str, l, i);
permute(str, l + 1, r);
str = swap(str, l, i); // Возврат к исходному состоянию
}
}
}

public static String swap(String str, int i, int j) {
char[] charArray = str.toCharArray();
char temp = charArray[i];
charArray[i] = charArray[j];
charArray[j] = temp;
return String.valueOf(charArray);
}

public static void main(String[] args) {
String str = "ABC";
int n = str.length();
permute(str, 0, n - 1);
}
}
Этот код генерирует все перестановки строки "ABC" и выводит их.


#Java #Training #Medium #Recursion
День программиста в России — это профессиональный праздник, который отмечается ежегодно 13 сентября (или 12 сентября в високосный год).
Этот праздник был официально утверждён в 2009 году, но история его появления имеет более глубокие корни.


Истоки праздника

Идея праздника для программистов возникла задолго до его официального признания. В середине 2000-х годов в среде программистов обсуждалась возможность учреждения специального дня, посвящённого их профессии. Инициатором этой идеи был Валентин Балт, один из сотрудников компании «Параллельные технологии», которая занималась разработкой программного обеспечения.

Почему 256-й день года?

Программисты выбрали для своего праздника 256-й день года, потому что число 256 — важное и символическое в мире программирования. Это максимальное количество чисел, которое можно выразить с помощью одного байта (8 бит). В бинарной системе 256 — это 2 в степени 8 (2^8). Такое количество часто встречается в компьютерных системах и цифровых технологиях.

Официальное признание

В 2002 году Валентин Балт инициировал сбор подписей за введение Дня программиста как официального праздника. Петиция нашла поддержку среди работников ИТ-индустрии, и в 2009 году правительство Российской Федерации официально утвердило этот праздник.

10 сентября 2009 года президент Дмитрий Медведев подписал указ № 1034 «О Дне программиста». Таким образом, День программиста стал официальным профессиональным праздником, который отмечается ежегодно 13 сентября (или 12 сентября в високосные годы).

Традиции празднования

Хотя День программиста не является государственным выходным, его активно отмечают в компаниях, связанных с информационными технологиями. В этот день:
Организуются корпоративные мероприятия для программистов, хакатоны и конкурсы.
Работодатели часто поощряют своих сотрудников-программистов наградами или приятными бонусами.
Некоторые компании организуют тематические вечеринки или неформальные встречи.

Значение праздника

Этот день стал символом признания важности работы программистов в современном мире. Информационные технологии и программное обеспечение играют ключевую роль в экономике, промышленности и повседневной жизни. Программисты создают продукты и решения, которые упрощают жизнь людей, ускоряют научный прогресс и трансформируют практически все отрасли человеческой деятельности.
Таким образом, День программиста в России не только напоминает о технических аспектах работы, но и подчёркивает культурное и социальное значение профессии в цифровом мире.


С праздником коллеги!🎉
Pair

В программировании часто возникает необходимость работать с парами значений, например, для хранения координат точки на плоскости, ключей и значений в словаре, или даже результатов вычислений. В Java нет встроенного класса Pair в стандартной библиотеке, однако многие библиотеки, такие как Apache Commons и JavaFX, предоставляют свою реализацию этого класса.

Класс Pair используется для хранения двух связанных объектов, которые могут быть разного типа. Эти объекты часто называют first и second (или key и value), что делает класс удобным для хранения связок данных, которые логически объединены. Например, Pair может использоваться для хранения координат точки (x, y), имени и фамилии, ключа и значения в словаре, и т.д.

Простейшая реализация класса Pair может выглядеть следующим образом:
public class Pair<K, V> {
private final K key;
private final V value;

public Pair(K key, V value) {
this.key = key;
this.value = value;
}

public K getKey() {
return key;
}

public V getValue() {
return value;
}

@Override
public String toString() {
return "(" + key + ", " + value + ")";
}
}


Эта реализация использует дженерики (K и V), что позволяет создавать пары объектов любого типа. Например, можно создать пару с типами String и Integer, что может быть полезно для хранения данных типа "имя-возраст":
Pair<String, Integer> person = new Pair<>("John", 30);
System.out.println(person.getKey()); // Выводит: John
System.out.println(person.getValue()); // Выводит: 30


Особенности использования Pair

Класс Pair обладает несколькими особенностями, которые делают его удобным инструментом в разработке:
Простота и универсальность: Pair позволяет легко объединять два объекта любого типа в одну сущность, не требуя создания отдельных классов для каждой комбинации типов.
Иммутабельность (неизменяемость): В большинстве реализаций класса Pair значения полей key и value устанавливаются только в момент создания объекта и не могут быть изменены впоследствии. Это обеспечивает безопасность данных и предотвращает их случайное изменение.
Поддержка дженериков: Возможность использовать дженерики позволяет создавать пары любых типов, что делает класс Pair универсальным инструментом для хранения данных.
Совместимость с различными библиотеками: Многие популярные библиотеки, такие как Apache Commons и JavaFX, содержат свои реализации класса Pair, что облегчает интеграцию с другими инструментами и фреймворками.


Внутреннее устройство Pair

Внутреннее устройство класса Pair на примере его реализации в библиотеке Apache Commons. Эта библиотека предоставляет готовый класс Pair, который можно использовать в своем проекте, добавив зависимость в ваш проект.

Пример реализации Pair из Apache Commons:
public class Pair<L, R> implements Map.Entry<L, R>, Comparable<Pair<L, R>>, Serializable {
private static final long serialVersionUID = 1L;
private final L left;
private final R right;

public Pair(L left, R right) {
this.left = left;
this.right = right;
}

public L getLeft() {
return left;
}

public R getRight() {
return right;
}

@Override
public int hashCode() {
return left.hashCode() ^ right.hashCode();
}

@Override
public boolean equals(Object o) {
if (!(o instanceof Pair)) {
return false;
}
Pair<?, ?> pair = (Pair<?, ?>) o;
return Objects.equals(left, pair.left) &&
Objects.equals(right, pair.right);
}

@Override
public String toString() {
return "(" + left + ", " + right + ")";
}

@Override
public int compareTo(Pair<L, R> other) {
int cmp = ((Comparable<L>) this.left).compareTo(other.left);
if (cmp != 0) {
return cmp;
}
return ((Comparable<R>) this.right).compareTo(other.right);
}
}


#Java #Training #Medium #Pair