Comprendre quand et comment utiliser Java 8 Lambdas


J'ai passé du temps à essayer d'apprendre certaines des nouvelles fonctionnalités de Java 8. À titre d'exercice, j'ai écrit un MergeSort en utilisant des interfaces fonctionnelles Java 8. J'inclus le code complet ci-dessous (des bogues/optimisations peuvent exister, je ne m'y intéresse que s'ils concernent les fonctionnalités Java 8). Ma question est, je crois qu'il existe des possibilités d'utiliser des expressions lambda lorsque j'utilise mes interfaces fonctionnelles, mais ce n'est tout simplement pas encore un clic dans mon cerveau. Il se sent comme chaque fois que j'appelle apply, il devrait y avoir un moyen d'utiliser "->" à la place. Quelqu'un peut-il me montrer la lumière?

Fonction de fusion écrite à l'aide de l'interface fonctionnelle 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 écrit en java.util.fonction.Fonction

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 )));

}

}

Main avec un cas de test simple

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)));
}

}

Produit

[1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 12, 23, 365]
Author: Denial, 2014-07-20

1 answers

, L'idée d'expressions lambda est qu'au lieu de créer une classe qui implémente une interface fonctionnelle, vous pouvez définir une expression lambda du type de l'interface.

Par exemple, votre classe Merge implémente BinaryOperator<int[]> et peut être remplacée par l'expression lambda suivante :

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;
};

Maintenant, nous pouvons également créer une expression lambda pour remplacer la classe MergeSort, et, en combinant les deux lambdas, nous obtenons:

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)));
    }
}

Quelques points concernant ce code :

  1. , j'ai dû renommer le paramètre de mergeSort lambda à partir de t à l depuis t est également utilisé dans le merge lambda.
  2. J'ai dû déclarer le mergeSort lambda en tant que membre statique (avant d'attribuer sa valeur), car il contient des appels récursifs à lui-même.
 14
Author: Eran, 2014-07-21 01:24:34