Статьи Генератор паролей UUID MD5 Unix-время URL-encode Base64 Форматирование XML Ваш внешний IP Число прописью


Список статей

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

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

Ранее мы рассматривали наиболее популярные Коллекции в Java. В данной статье рассмотрим чуть более специфичные коллекции. Все рассмотренные ниже коллекции реализуют один из двух алгоритмов манипулирования данными: «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());
}
Читать полностью...

Терминальные операции Stream API

8 апреля 2019

Тэги: Java 8 Collections Stream API

Ранее мы уже рассмотрели Промежуточные операции Stream API, а сейчас рассмотрим терминальные (конечные).

Промежуточные операции следует воспринимать как «отложенные», т.е. они не меняют сами данные, а только задают правила их изменения. А терминальные как раз инициируют всю цепочку преобразований, закрывают поток и возвращают модифицированные данные. Закрытый поток повторно использовать нельзя.

Преобразование в коллекцию

Самая распространённая терминальная операция collect(). Результатом может быть, например, список.

List<String> fruits = Stream.of("apple", "banana", "lemon", "orange")
        // здесь могут быть ещё какие-то преобразования
        .collect(Collectors.toList());

А можно преобразовать стрим из строк в мапу, причём ключом сделать первую букву соответствующего слова:

Map<String, String> fruits = Stream.of("apple", "banana", "lemon", "orange")
        .collect(Collectors.toMap(e -> e.substring(0, 1), e -> e));
        // {a=apple, b=banana, l=lemon, o=orange}
Читать полностью...

Промежуточные операции Stream API

7 апреля 2019

Тэги: Stream API Java 8 Collections

Все методы Stream API можно разделить на две группы: промежуточные и терминальные (конечные). Промежуточные операции следует воспринимать как «отложенные», т.е. они не меняют сами данные, а только задают правила их изменения. А терминальные как раз инициируют всю цепочку преобразований и возвращают модифицированные данные.

Рассмотрим промежуточные операции. Все промежуточные операции возвращают типизированный интерфейс Stream<>.

Преобразование

Любое изменение исходного элемента можно делать с помощью метода map(). В качестве параметра метод принимает лямбда-выражение.

Stream.of(1, 2, 3, 4, 5, 6)
        .map(n -> n * 10) // умножает каждый элемент на 10
Stream.of("apple", "orange")
        .map(String::toUpperCase) // преобразует буквы в каждом слове в верхний регистр

Во втором случае мы воспользовались краткой записью лямбда-выражения через method reference.

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

CrudRepository в Spring Data

27 мая 2018

Тэги: Java 8 PostgreSQL Spring Boot rest Spring Hibernate Spring Data

В статье Hibernate и Spring Boot мы рассматривали использование Hibernate для того, чтобы не писать sql-запросы в слое доступа к данным. Сегодня мы пойдём ещё дальше и рассмотрим, как Spring Data может генерировать за вас сам слой доступа к данным со всеми методами, которые вам нужны в сервисном слое.

В качестве примера возьмём сущность «Страна» с её названием в качестве единственного параметра и на примере этой сущности шаг за шагом создадим все необходимые операции для поиска, добавления, редактирования и удаления этой сущности. В СУБД postgres надо создать следующую таблицу:

CREATE TABLE country
(
  id serial,
  name character varying(50) NOT NULL,
  CONSTRAINT country_id_pk PRIMARY KEY (id)
);

Теперь создадим типовой maven-проект и добавим в pom.xml необходимые зависимости. Полную версию файла можно посмотреть на github.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.12.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.2.2.jre7</version>
    </dependency>
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.0</version>
    </dependency>
</dependencies>

spring-boot-starter-web отвечает за обработку http-запросов, а spring-boot-starter-data-jpa предоставляет функционал доступа к данным. Также мы добавляем драйвер для работы с целевой СУБД.

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

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:

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

Работа с датой в Spring Boot

12 мая 2018

Тэги: Spring Boot Java PostgreSQL

В предыдущих статьях мы уже создавали rest-приложение (Spring Boot Restful Service, Работа с БД в Spring Boot на примере postgresql). А теперь давайте рассмотрим, как работать с датой и временем в Spring Boot на уровне rest-запросов и на уровне БД.

Предположим, перед нами стоит задача фиксировать в специальной таблице все действия пользователя (регистрация, вход, выход и т.п.) Таблица для СУБД Postgres в самом простом случае будет выглядеть так:

CREATE TABLE user_action
(
   id serial NOT NULL,
   action_date timestamp without time zone NOT NULL,
   user_id integer NOT NULL,
   action_type integer NOT NULL,
   CONSTRAINT user_action_pk PRIMARY KEY (id)
)

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

Тип timestamp without time zone позволяет хранить метку времени без привязки к часовому поясу.

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

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

Коллекции: list, set, map

8 мая 2018

Тэги: Java Collections

Под коллекциями в программировании подразумевают объекты, которые хранят внутри себя какой-либо набор значений и предоставляют набор методов для обращения к этим значениям. В Java можно выделить 3 наиболее часто используемых типа коллекций: списки (list), наборы (set) и словари (map). При объявлении коллекции типизируются каким-либо типом, т.е. одна коллекция хранит данные одного типа.

Список (list)

Списки в Java реализуют интерфейс List, который, в свою очередь, расширяет интерфейс Collection. Список позволяет хранить любые значения, в том числе повторяющиеся. Итерация (обход) списка происходит в порядке добавления элементов. Т.е. элемент, добавленный первым, при итерации также будет первым.

List<String> list = new ArrayList<>();
list.add("яблоко");
list.add("ананас");
list.add("яблоко");
System.out.println(list); // На экране увидим: [яблоко, ананас, яблоко]

Две наиболее частые реализации интерфейса List - это ArrayList и LinkedList.

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

Как получить параметры окружения в Java

7 мая 2018

Тэги: Java

Метод System.getProperties() возвращает список системных свойств (параметров окружения), доступных для данной виртуальной машины. Свойство представляет из себя пару «ключ-значение». Среди полученных свойств всегда можно обнаружить следующие:

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

Настройка postgres для доступа по сети

6 мая 2018

Тэги: PostgreSQL

Для того, чтобы открыть доступ по локальной сети с других машин к БД, которая развёрнута на данной, нужно отредактировать два файла: postgresql.conf и pg_hba. Привожу пример для своей операционной системы, основанной на Linux (Ubuntu) и postgresql 9.5.

В файле /etc/postgresql/9.5/main/postgresql.conf находим строку

listen_addresses = '*'

и раскомментируем её (убираем решётку в начале строки) или добавляем, если такой строки в этом файле нет.

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

Затем в файле /etc/postgresql/9.5/main/pg_hba.conf с правами администратора нужно указать, какие хосты имеют право подключаться к указанной БД и каким образом обеспечивается безопасность подключения.

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

❮ Назад Далее ❯