Статьи

Статьи с тэгом «Java»

Как получить последний день месяца

30 сентября 2020

Тэги: Java Java 8 Kotlin

При работе с датами часто бывает нужно получить последний день текущего месяца или года. Поскольку последний день года всегда равен 31 декабря, то мы можем напрямую создать эту дату с помощью метода LocalDate.of(). А вот последний день месяца зависит от конкретного месяца. Дней в месяце может быть 30 или 31, а для февраля и вовсе 28 или 29.

Чтобы не разбираться в логике работы календаря, начиная с Java 8 (а, значит, и в Kotlin) нам доступен специальный класс TemporalAdjusters. Он имеет несколько полезных методов, но в данном случае нас интересует lastDayOfMonth(), возвращающий специальный объект с интерфейсом TemporalAdjuster. Этот интерфейс содержит метод adjustInto(), который позволяет «выравнивать» любую переданную ему дату (или дату со временем) по определённому правилу. В нашем случае дата будет выровнена по последнему дню месяца.

Читать полностью...

Работа с коллекциями в Kotlin и Java

28 сентября 2020

Тэги: Kotlin Java Collections Java 11 Stream API

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

Создаём класс-сущность

Для того, чтобы нам было от чего отталкиваться, создадим класс-сущность. То есть это класс, предназначенный для хранения данных. Часто в корпоративных приложениях поля таких классов мапятся один к одному на поля таблицы в базе данных. Для примера рассмотрим сущность «Город», у которой есть два атрибута: название и количество проживающих в нём людей.

Читать полностью...

Сравнение форматов конфига в Spring Boot

16 февраля 2020

Тэги: Spring Boot Java Collections Spring

Spring Boot позволяет хранить настройки приложения в файле и получать к ним доступ в декларативном стиле. Этот файл может иметь один из трёх форматов: properties, xml и yaml. Как Spring будет интерпретировать формат файла, определяется его расширением. Далее мы рассмотрим плюсы и минусы каждого формата. В качестве примера предположим, что в конфиге мы храним число, текстовую строку на русском языке и список значений.

properties-файл

По умолчанию в Spring используется properties-конфиг. Имя файла должно начинаться со слова application и иметь расширение properties. Если вы не используете профили для разделения конфигов, то достаточно иметь файл application.properties.

# числовой параметр
some.test.numberValue=42
# текстовый параметр
some.test.textValue="Текстовый параметр из properties-файла"
# список значений
some.test.list[0]=one
some.test.list[1]=two
some.test.list[2]=three

В данном формате комментарии всегда начинаются с новой строки и с символа «#». Имя каждого параметра прописывается полностью (и это один из недостатков данного формата), затем идёт «=», затем само значение. Текстовые значения можно указывать как в кавычках, так и без них. Список значений, который в нашем приложении превратится в объект типа List, в конце имени каждого значения имеет индекс в квадратных скобках. Такой синтаксис похож на объявление массива.

Читать полностью...

Чтение вводимых значений с консоли

22 января 2020

Тэги: Java 10 Java

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

var scanner = new Scanner(System.in);
System.out.print("Введите Ваше имя: ");
var username = scanner.nextLine();
System.out.print("Сколько Вам лет? ");
var age = scanner.nextInt();
System.out.println(String.format("Ваше имя: %s, ваш возраст: %s", username, age));

В конструктор этого класса передаётся стандартный поток ввода System.in. Далее мы запрашиваем у пользователя его имя с помощью метода nextLine(). Этот метод вернёт всю строку, которую введёт пользователь в консоли до нажатия клавиши Enter.

Читать полностью...

Алгоритм поиска простых чисел

7 мая 2019

Тэги: Java алгоритмы

Простое число - это число, которое делится нацело без остатка только на 1 и на самого себя. Также известно, что любое целое число, большее 1, является либо простым, либо может быть выражено как произведение простых чисел. Ряд простых чисел начинается с 2 и имеет следующий вид: 2, 3, 5, 7 и т.д.

Рассмотрим более-менее оптимальный алгоритм поиска простых чисел. Для этого давайте реализуем на Java метод getFirstPrimes(), который будет возвращать N первых простых чисел.

public List<Integer> getFirstPrimes(int count) {
    List<Integer> primes = new ArrayList<>();
    if (count > 0) {
        primes.add(2);
    }
    for (int i = 3; primes.size() < count; i += 2) {
        if (isPrime(i, primes)) {
            primes.add(i);
        }
    }
    return primes;
}

Все найденные простые числа будем складывать в список. Далее проверяем, что если у нас запросили хотя бы одно простое число, то сразу добавим 2, т.к. с него начинается последовательность. Далее в цикле начинаем проверять числа, сразу начиная с трёх. Также обратите внимание, что мы проверяем только нечётные числа (приращение +2), т.к. все чётные числа по определению делятся на 2.

Читать полностью...

Валидация бинов в Spring

28 апреля 2019

Тэги: Java Spring

Spring позволяет проверять формат данных в бинах в декларативном стиле при помощи специальных аннотаций из пакета javax.validation.

Предположим, у нас есть rest-контроллер, в который мы хотим добавить метод, создающий пользователя. Очевидно, что это будет POST-запрос:

@PostMapping("/users")
public String createUser(@Valid @RequestBody CreateUserRequest request) {
    // создание пользователя в БД
    return "Success";
}

На вход метод принимает бин CreateUserRequest, который мы будем передавать в формате json. Этот параметр метода снабжён аннотациями @RequestBody (говорит, что параметр будет именно в теле запроса) и @Valid (аннотация, которая активирует механизм валидации для данного бина). Обратите внимание, что если не указать аннотацию @Valid, то валидация работать не будет.

Читать полностью...

Конфигурационные файлы в Spring Boot

25 апреля 2019

Тэги: Spring Boot rest Java

Значения параметров системы удобно отделять от программного кода, чтобы можно было их менять без перекомпиляции всего приложения. Spring Boot предоставляет нам удобный способ работы с конфигурационными файлами. Ниже мы рассмотрим несколько случаев, начиная с самого простого.

Исходники доступны на github.

Одиночные параметры

Отдельное свойство можно внедрить в любой компонент Spring при помощи аннотации @Value.

Предположим, у нас есть простейшее Spring Boot приложение, в котором есть rest-контроллер с методами.

Добавим метод, который в ответ возвращает приветственный текст для пользователя, а имя пользователя будем брать из конфига.

Читать полностью...

Введение в многопоточность

25 апреля 2019

Тэги: Java многопоточность

Есть два способа создания потоков в Java: унаследоваться от класса Thread или реализовать интерфейс Runnable.

Создание потока через наследование

Рассмотрим пример, в котором мы расширяем стандартный класс Thread, переопределяя лишь один метод run(). В нём мы ждём 3 секунды, а затем выводим сообщение о завершении потока. Обратите внимание, что запуск потока осуществляется не через метод run(), а через метод start().

public class ThinkerThread extends Thread {

    @Override
    public void run() {
        try {
            TimeUnit.SECONDS.sleep(3); // аналогично Thread.sleep(3000L);
            System.out.println("Второй поток завершён");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    public static void main(String[] args) {
        new ThinkerThread().start();
        System.out.println("Основной поток завершён");
    }
}

Метод TimeUnit.SECONDS.sleep() полностью эквивалентен стандартному Thread.sleep(), однако в первом случае мы явно указываем единицы измерения времени, что делает код более читаемым. Я рекомендую использовать именно такую форму записи.

Поскольку метод sleep() относится к низкоуровневым, он может кидать InterruptedException, которое свидетельствует о том, что поток был прерван. Это исключение является единственным признаком того, что поток был принудительно остановлен. И чтобы не терять эту информацию в стеке вызовов, мы выставляем флаг interrupted при помощи соответствующего метода Thread.currentThread(). Такой способ обработки InterruptedException является правильным и именно его нужно использовать в подобных случаях.

Читать полностью...

Коллекции: очередь и стек

16 апреля 2019

Тэги: Collections Java

Ранее мы рассматривали наиболее популярные Коллекции: list, set, map. В данной статье рассмотрим чуть более специфичные коллекции. Все рассмотренные ниже коллекции реализуют один из двух алгоритмов манипулирования данными: «First In - First Out» (FIFO) и «Last In - First Out» (LIFO).

Очередь

Очередь реализует принцип «first in - first out», т.е. «первым пришёл - первым ушёл». Базовым интерфейсом всех очередей Java является Queue. Добавление элементов в очередь делается методом add(), удаление - poll(), получение первого элемента без его удаления - peek().

Две самые простые реализации очереди - это LinkedList и PriorityQueue. Рассмотрим их на примере.

Queue<String> queue = new LinkedList<>();
queue.add("банан");
queue.add("яблоко");
queue.add("ананас");
while (queue.peek() != null) { // или !queue.isEmpty()
    System.out.println(queue.poll());
}
Читать полностью...

Hibernate и Spring Boot

20 мая 2018

Тэги: Spring Boot maven PostgreSQL rest Spring Java Hibernate

Ранее мы уже рассматривали, как работать с базой данных через jdbc в статье Работа с БД в Spring Boot на примере postgresql. А сегодня возьмём Hibernate - самый популярный фреймворк для работы с БД - и убедимся, что он значительно облегчает реализацию типовых операций над сущностями.

Предположим, в БД у нас есть две сущности: страна и город. В одной стране может быть несколько городов (отношение «один-ко-многим»). Структура таблиц выглядит примерно так:

CREATE SEQUENCE country_id_seq;

CREATE TABLE country
(
  id integer NOT NULL DEFAULT nextval('country_id_seq'::regclass),
  name character varying(50) NOT NULL,
  CONSTRAINT country_id_pk PRIMARY KEY (id)
);

CREATE SEQUENCE city_id_seq;

CREATE TABLE city
(
  id integer NOT NULL DEFAULT nextval('city_id_seq'::regclass),
  name character varying(50) NOT NULL,
  country_id integer NOT NULL
);

И мы хотим совершать типовые действия над этими сущностями: просмотр всего списка, поиск по id, добавление, обновление и удаление записей. Для этого создадим типовой Spring Boot проект. В pom-файле нужно прописать следующий parent:

Читать полностью...

Далее ❯