Подтвердить что ты не робот

Понимание того, когда и как использовать Java 8 Lambdas

Я потратил некоторое время на изучение некоторых новых возможностей Java 8. В качестве упражнения я написал MergeSort, используя некоторые функциональные интерфейсы Java 8. Я включаю полный код ниже (ошибки/оптимизации могут существовать, меня интересуют только они, если они относятся к функциям Java 8). Мой вопрос в том, что я считаю, что есть возможности использовать лямбда-выражения, когда я использую свои функциональные интерфейсы, но это просто не щелкнуло в моем мозгу. Кажется, каждый раз, когда я звоню, я должен использовать способ "- > ". Может кто-нибудь, пожалуйста, покажет мне свет?

Функция слияния, написанная с использованием функционального интерфейса BinaryOperator

public class Merge implements BinaryOperator<int[]>{

@Override
public int[] apply(int[] t, int[] u) {

    int[] result = new int[t.length + u.length];

    for (int i = 0, j = 0, k = 0; i < result.length; i++){

        if( j == t.length){
            result[i] = u[k++];
        } else if (k == u.length) {
            result[i] = t[j++];
        } else {
            result[i] = t[j] < u [k] ? t[j++] : u[k++];
        }

    }

    return result;
}

}

MergeSort, написанный как функция java.util.function.Function

public class MergeSort implements Function<int[], int[]>{

Merge merge = new Merge();

@Override
public int[] apply(int[] t) {

    if(t.length <= 1){
        return t;
    }

     return merge.apply( apply(Arrays.copyOfRange(t, 0, t.length / 2)), 
                         apply(Arrays.copyOfRange(t, t.length / 2, t.length )));

}

}

Главная с одним простым тестовым примером

public class MergeSortMain {

public static void main(String[] args) {

    int values[] = {3,12,6,7,2,1,23,4,5,7,8,4,2,5,365};

    MergeSort mergeSort = new MergeSort();

    System.out.println(Arrays.toString(mergeSort.apply(values)));
}

}

производит

[1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 12, 23, 365]
4b9b3361

Ответ 1

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

Например, ваш класс Merge реализует BinaryOperator<int[]> и может быть заменен следующим выражением лямбда:

BinaryOperator<int[]> merge = (t,u) -> {
    int[] result = new int[t.length + u.length];
    for (int i = 0, j = 0, k = 0; i < result.length; i++){
        if( j == t.length){
            result[i] = u[k++];
        } else if (k == u.length) {
            result[i] = t[j++];
        } else {
            result[i] = t[j] < u [k] ? t[j++] : u[k++];
        }
    }
    return result;
};

Теперь мы также можем создать лямбда-выражение для замены класса MergeSort, и, объединив два лямбда, получим:

public class MergeSortMain {
    public static Function<int[], int[]> mergeSort;
    public static void main(String[] args) {
        int values[] = {3,12,6,7,2,1,23,4,5,7,8,4,2,5,365};
        mergeSort = l -> {
            BinaryOperator<int[]> merge = (t,u) -> {
                int[] result = new int[t.length + u.length];
                for (int i = 0, j = 0, k = 0; i < result.length; i++){
                    if( j == t.length){
                        result[i] = u[k++];
                    } else if (k == u.length) {
                        result[i] = t[j++];
                    } else {
                        result[i] = t[j] < u [k] ? t[j++] : u[k++];
                    }
                }
                return result;
            };
            if(l.length <= 1){
                return l;
            }
            return merge.apply( mergeSort.apply(Arrays.copyOfRange(l, 0, l.length / 2)), 
                                mergeSort.apply(Arrays.copyOfRange(l, l.length / 2, l.length )));
        };
        System.out.println(Arrays.toString(mergeSort.apply(values)));
    }
}

Некоторые моменты, касающиеся этого кода:

  • Мне пришлось переименовать параметр MergeSort lambda от t до l, так как t также используется в Merge lambda.
  • Мне пришлось объявить лямбда MergeSort как статический член (до назначения его значения), поскольку он содержит рекурсивные вызовы к себе.