Статьи

Java 8: тестирование лямбда-воды

До Java 8 около года и поставляется с языковой функцией, которую я очень жду: лямбда-выражение . К сожалению, другая важная функция, Модули для платформы Java, была отложена до Java 9. Но, тем не менее, введение лямбда-выражений (или замыканий, если хотите) в язык сделает программирование на Java намного лучше.

Таким образом, пройдет почти год — но поскольку Java сейчас разрабатывается с открытым исходным кодом, мы можем взглянуть и попробовать использовать ее прямо сейчас. Итак, начнем!

Загрузите и установите Lambda с поддержкой Java 8

Во-первых, я ожидал, что мне придется самому скомпилировать Java 8, поскольку он еще не выпущен. Но я был приятно удивлен, увидев, что бинарная сборка доступна для всех платформ по адресу http://jdk8.java.net/lambda/ . Поэтому я только что скачал последнюю версию предварительной сборки для разработчиков и установил ее на свой компьютер.

Чтобы убедиться, что это работает, я создал класс LambdaIntro, содержащий «Hello, World!», Скомпилировал и выполнил его:

1
2
3
4
5
~ $ export JAVA_HOME=~/Devtools/Java/jdk1.8.0/
~ $ cd spikes/lambda-water
~ $ $JAVA_HOME/bin/javac  src/net/jthoenes/blog/spike/lambda/LambdaIntro.java
~ $ $JAVA_HOME/bin/java -cp src net.jthoenes.blog.spike.lambda.LambdaIntro
Hello from Java 8!

Примечание : я использую командную строку для компиляции и выполнения здесь, потому что IDE не поддерживают Java 8 на данный момент.

Не Лямбда Путь

В качестве примера давайте предположим, что я хочу просмотреть список объектов. Но для моей бизнес-логики мне нужно иметь значение и индекс элемента списка. Если я хочу сделать это с текущей Java, я должен обработать индекс вместе с реальной логикой:

1
2
3
4
List list = Arrays.asList('A', 'B', 'C');
for (int index = 0; index < list.size(); index++) {     String value = list.get(index);     String output = String.format('%d -> %s', index, value);
    System.out.println(output);
}

Это будет выводить

1
2
3
0 -> A
1 -> B
2 -> C

Это не так уж плохо, но я сделал две вещи в одних и тех же нескольких строках кода: управление итерацией и предоставление некоторой (очень простой) бизнес-логики. Лямбда-выражения могут помочь мне разделить эти два. \

Подпись метода eachWithIndex

Поэтому я хочу иметь метод eachWithIndex, который можно вызвать так:

1
2
3
4
5
6
7
List list = Arrays.asList('A', 'B', 'C');
eachWithIndex(list,
    (value, index) -> {
        String output = String.format('%d -> %s', index, value);
        System.out.println(output);
    }
);

Метод получает два параметра. Первый — это список, а второй — лямбда-выражение или замыкание, которое указывает методу, что делать с каждым элементом списка. Как видно из строки 3, лямбда-выражение получает два аргумента: текущее значение и текущий индекс. Эти аргументы не имеют объявления типа. Информация о типе будет выведена компилятором Java 8. После аргументов есть -> и блок кода, который должен быть выполнен для каждого элемента списка.

Примечание : вам придется написать этот метод в обычном текстовом редакторе или игнорировать сообщения об ошибках в вашей IDE.

Реализуйте метод eachWithIndex

Чтобы использовать лямбду в Java 8, вам нужно объявить функциональный интерфейс. Функциональный интерфейс — это интерфейс, который имеет ровно один метод — метод, который будет реализован лямбда-выражением. В этом случае мне нужно объявить метод, который получает элемент и индекс и ничего не возвращает. Поэтому я определяю следующий интерфейс:

1
2
3
public static interface ItemWithIndexVisitor<E> {
    public void visit(E item, int index);
}

С помощью этого интерфейса я могу теперь реализовать метод eachWithIndex .

1
2
3
4
5
public static <E> void eachWithIndex(List<E> list, ItemWithIndexVisitor<E> visitor) {
    for (int i = 0; i < list.size(); i++) {
         visitor.visit(list.get(i), i);
    }
}

В методе используется универсальный параметр <E> , поэтому будет выведено, что элемент, переданный методу посещения, того же типа, что и список.

Преимущество использования функциональных интерфейсов состоит в том, что их много в Java. Вспомните, например, интерфейс java.util.concurrent.Callable . Он может использоваться как лямбда-код без изменения кода, который использует Callable . Это делает большую часть лямбды JDK и фреймворков включенной по умолчанию.

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

Одна маленькая удобная вещь из Project Lambda — это ссылки на методы. Это способ повторно использовать существующие методы и упаковать их в объект функционального интерфейса. Допустим, у меня есть следующий метод

1
2
3
4
public static <E> void printItem(E value, int index) {
    String output = String.format('%d -> %s', index, value);
    System.out.println(output);
}

и я хочу использовать этот метод в моем методе eachWithIndex , чем я могу использовать нотацию :: внутри моего вызова метода:

1
eachWithIndex(list, LambdaIntro::printItem);

Выглядит красиво и лаконично, не так ли?

Резюме

Это запускает мой первый лямбда-пример. Я не мог избежать улыбки на лице, чтобы увидеть замыкания, запущенные в одной из моих Java-программ, после того, как они так долго тосковали по ним. В настоящее время лямбда-выражения доступны только для предварительного просмотра. Если вы хотите узнать больше, прочтите текущий предварительный обзор проекта или перейдите на страницу проекта Project Lambda .

Я загрузил полный пример кода в суть .

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