Статьи

Простое применение лямбда-выражений в Java 8

Я пытался вписать лямбда-выражения в код, который я пишу, и этот простой пример является следствием того же самого. Для тех, кто не знает о лямбда-выражениях в Java, я бы порекомендовал им сначала прочитать это, прежде чем приступать к этой статье.

Хорошо, теперь, когда вы знакомы с лямбда-выражениями (после прочтения вводного поста), давайте перейдем к простому примеру, который я считаю хорошим использованием лямбда-выражений.

Рассмотрим следующий сценарий: определенная операция окружена некоторой предварительной обработкой и некоторой последующей обработкой. И выполняемая операция может варьироваться в зависимости от

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

Давайте посмотрим, как это можно сделать с использованием интерфейсов и их реализаций через классы Anonymous Inner.

Использование анонимных внутренних классов

Интерфейс, который должен быть реализован для обеспечения требуемого поведения:

1
2
3
interface OldPerformer {
  public void performTask(String id, int status);
}

И давайте посмотрим на метод, который выполняет предварительную обработку, выполняет требуемую операцию и затем последующую обработку:

1
2
3
4
5
6
7
8
9
public class PrePostDemo {
  static void performTask(String id, OldPerformer performer) {
    System.out.println("Pre-Processing...");
    System.out.println("Fetching the status for id: " + id);
    int status = 3;//Some status value fetched
    performer.performTask(id, status);
    System.out.println("Post-processing...");
  }
}

Нам нужно передать 2 вещи — идентификатор для выполнения предварительной обработки и реализацию операции, что можно сделать, как показано ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class PrePostDemo {
  public static void main(String[] args) {
    //has to be declared final to be accessed within
    //the anonymous inner class.
    final String outsideOfImpl = "Common Value";
    performTask("1234", new OldPerformer() {
      @Override
      public void performTask(String id, int status) {
        System.out.println("Finding data based on id...");
        System.out.println(outsideOfImpl);
        System.out.println("Asserting that the status matches");
      }
    });
    performTask("4567", new OldPerformer() {
      @Override
      public void performTask(String id, int status) {
        System.out.println("Finding data based on id...");
        System.out.println(outsideOfImpl);
        System.out.println("Update status of the data found");
      }
    });
  }
}

Как видно выше, переменные, объявленные вне внутреннего класса Anonymous, должны быть объявлены как final, чтобы они были доступны в методах внутреннего анонимного класса. Вывод приведенного выше кода будет:

01
02
03
04
05
06
07
08
09
10
11
12
Pre-Processing...
Fetching the status for id: 1234
Finding data based on id...
Common Value
Asserting that the status matches
Post-processing...
Pre-Processing...
Fetching the status for id: 4567
Finding data based on id...
Common Value
Update the status of the data found
Post-processing...

Использование лямбда-выражения

Давайте посмотрим, как написанное выше можно написать с помощью лямбда-выражения:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class PrePostLambdaDemo {
  public static void main(String[] args) {   
    //Need not be declared as final for use within a
    //lambda expression, but has to be eventually final.
    String outsideOfImpl = "Common Value";
 
    doSomeProcessing("123", (String id, int status) -> {
      System.out.println("Finding some data based on"+id);
      System.out.println(outsideOfImpl);
      System.out.println("Assert that the status is "+status );
    });
 
    doSomeProcessing("456", (String id, int status) -> {
      System.out.print("Finding data based on id: "+id);
      System.out.println(outsideOfImpl);
      System.out.println("And updating the status: "+status);
    });
  }
 
  static void doSomeProcessing(String id, Performer performer ){
    System.out.println("Pre-Processing...");
    System.out.println("Finding status for given id: "+id);
    int status = 2;
    performer.performTask(id, status);
    System.out.println("Post-processing...");
  }
}
 
interface Performer{
public void performTask(String id, int status);
}

Помимо интересного синтаксиса лямбда-выражения, переменная вне области лямбда-выражения не объявляется как окончательная. Но он должен быть в конечном итоге окончательным, что означает, что значение переменной: outsideOfImpl не должно изменяться после объявления.

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

Напутствие: выпуск релиза JDK 8 перенесен на февраль 2014 года, а полное расписание можно найти здесь . Я использую лямбда-сборку Project, которая обновляется каждый день, поэтому не стесняйтесь сообщать мне, если что-то из этого не работает в последних сборках. Я буду стараться обновлять сборки и пробовать образцы, размещенные здесь.

Еще одно замечание: не волнуйтесь о том, что происходит в Java 8, эти функции уже являются частью многих языков программирования. Я обнаружил, что изучение синтаксиса и подхода лямбда-выражений в Java помогло мне понять и мыслить функционально и более конкретно оценить замыкания Scala.

Ссылка: простое приложение лямбда-выражений в Java 8 от нашего партнера по JCG Мохамеда Санауллы в блоге Experiences Unlimited .