Статьи

Функциональное программирование в Java 8 с Javaslang

Мы очень рады объявить о гостевом посте в блоге jOOQ, написанном Дэниелом Дитрихом , старшим инженером-программистом HSH Nordbank, мужем и отцом троих детей. В настоящее время он создает систему ценообразования для финансовых продуктов в качестве руководителя проекта и ведущего разработчика.

danieldietrich

Помимо своей работы он интересуется языками программирования, эффективными алгоритмами и структурами данных. Дэниел написал короткую книгу Play Framework Starter по созданию веб-приложений с использованием Play Framework для Java и Scala — и недавно создал Javaslang, библиотеку функциональных компонентов для Java 8 , которая особенно заинтересовала нас.

Это был действительно захватывающий момент, когда я услышал, что Java получит лямбды. Фундаментальная идея использования функций как средства абстракции берет свое начало в «лямбда-исчислении», 80 лет назад. Теперь разработчики Java могут передавать поведение с помощью функций.

1
2
3
4
List<Integer> list = Arrays.asList(2, 3, 1);
 
// passing the comparator as lambda expression
Collections.sort(list, (i1, i2) -> i1 - i2);

Лямбда-выражения значительно уменьшают многословность Java. Новый Stream API закрывает пробел между лямбдами и библиотекой Java-коллекции. При более внимательном рассмотрении видно, что параллельные потоки используются редко или, по крайней мере, с осторожностью. Поток не может быть повторно использован, и это раздражает, что коллекции должны быть преобразованы туда и обратно.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
// stream a list, sort it and collect results
Arrays.asList(2, 3, 1)
  .stream()
  .sorted()
  .collect(Collectors.toList());
         
// a little bit shorter
Stream.of(2, 3, 1)
  .sorted()
  .collect(Collectors.toList());
 
// or better use an IntStream?
IntStream.of(2, 3, 1)
  .sorted()
  .collect(ArrayList::new, List::add, List::addAll);
 
// slightly simplified
IntStream.of(2, 3, 1)
  .sorted()
  .boxed()
  .collect(Collectors.toList());

Вот Это Да! Это довольно много вариантов для сортировки списка целых чисел. Как правило, мы хотим сосредоточиться на том, что, а не оборачивать голову вокруг того, как . Это дополнительное измерение сложности не является необходимым. Вот как можно добиться того же результата с Javaslang :

1
List.of(2, 3, 1).sort();

Обычно каждый объектно-ориентированный язык имеет императивное ядро, как и Java. Мы контролируем поток наших приложений, используя условные операторы и циклы.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
String getContent(String location) throws IOException {
    try {
        final URL url = new URL(location);
        if (!"http".equals(url.getProtocol())) {
            throw new UnsupportedOperationException(
                "Protocol is not http");
        }
        final URLConnection con = url.openConnection();
        final InputStream in = con.getInputStream();
        return readAndClose(in);
    } catch(Exception x) {
        throw new IOException(
            "Error loading location " + location, x);
    }
}

Функциональные языки имеют выражения вместо утверждений, мы думаем в значениях. Лямбда-выражения помогают нам преобразовывать ценности. Вот один из примеров использования Javaslang’s Try :

1
2
3
4
5
6
7
8
Try<String> getContent(String location) {
    return Try
        .of(() -> new URL(location))
        .filter(url -> "http".equals(url.getProtocol()))
        .flatMap(url -> Try.of(url::openConnection))
        .flatMap(con -> Try.of(con::getInputStream))
        .map(this::readAndClose);
}

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

Я надеюсь, что это краткое введение вызвало у вас интерес к javaslang.com ! Пожалуйста, посетите сайт, чтобы узнать больше о функциональном программировании с Java 8 и Javaslang.