On Github BloumineX / ReXStreamLambda
Created by Xavier BLOUMINE / @bloumix
Développeur Java 6 Ans xp Passionné par le Clean Code et les best practices ! (TDD/BDD/DDD/Craftman/conférences/...)
En mission chez Natixis crédit consommation Contexte : JBoss EAP 6.4 / Java 8 / JPA / Rest / ...
Comparator<String> c = new comparator<String>() {
    @Override
    public boolean compare(String s1, String s2) {
        return s1.compageIgnoreCase(s2);
    } 
}
/// stuff there ///
list.sort(c);
                        
                            Utilisation d'une classe anonyme pour pouvoir utiliser le Comparator
                            Résultat : Rend le code moins lisible en devant réimplémenter la classe Comparator (cas simple)... 
                        
                        list.sort((s1, s2) -> s1.compareIgnoreCase(s2));Utilisation d'une Lambda
//On ne peux pas modifier une liste sur lequel on iterer
// donc on la copie dans une nouvelle liste
List< Integer> listResult = new ArrayList< >(list);
                            
//enlever les éléments impairs
for (Integer i : list) {
    if (i%2 != 0)
        listResult.remove(i);
}
//enlever les doublons
Set< Integer> setInte = new HashSet<>(listResult);
//Multiplier par 2 les élements et renvoyer la somme
Integer result = 0;
for (Integer i : setInte) {
    result = result + i * 2;
}
                        
                        
list.stream()
    .filter((value -> value % 2 != 0))
    .map(value -> value * 2)
    .distinct()
    .reduce(0, (val1, val2) -> val1 + val2)
                            
                    Rien de plus facile !
//le for n'a pas de d'équivalent pur car il est trop générique
//les streams peuvent parcourir les éléments facilement et faire des opérations dessus.
list.stream()
    .filter((value -> value % 2 != 0))
    .map(value -> value * 2)
    .distinct()
    .forEach(value -> System::println) //forEach ;)
                         
                Interface ne possédant qu'une seule méthode abstraite
Peut avoir n méthodes implémentées mais uniquement une méthode abstraite Sert de conteneur pour la méthode abstraiteL'Annotation @FunctionnalInterface indique au compilateur que cette interface est une interface Fonctionnelle
                            
@FunctionnalInterface
public Interface StringComparator {
    default int methodFolle(String a) { /* Some stuff there */}
    int compare(String a, String b);
}
                        La liste des interfaces fonctionnelles disponibles de l'api
Equivalent en C++ : functeur pointeur de fonction Le principe : encapsuler la methode abstraite au sein d'un objet java
Consumer< Integer> consumer = new Consumer< Integer>() {
    @Override
    public void accept(Integer integer) {
        System.out.println(integer);
    }
};
list.stream().forEach(consumer);
                        
Nous passons un objet et non une méthode !
                    
public class PrinterList {
//static obligatoire car il n'y a pas d'implementation !
    public static void print(Integer i) { 
        System.out.println(i);
    }
}
//Le compilateur va avec cette nouvelle syntaxe comprendre que cette méthode 
//peut etre utiliser en tant que Consumer
list.stream().forEach(PrinterList::print);
//Possibilité aussi de passer par : 
list.stream().forEach(System.out::println); 
                        
                        Même si le compilateur effectue des transformations en interne, nous envoyons maintenant notre méthode au lieu d'un objet !Nous devons quand même créer une classe pour paramètrer notre fonction 
                        
                    
list.stream().forEach((value) -> System.out.println(value));
                        
                        
//value n'a pas de parametre mais le compilateur sais le reconnaitre
Arrays.<String>asList("tst1", "tst2").stream()
        .forEach(value -> System.out.println(value));
//Lambda expression et inférence du type des paramètres
Arrays.<String>asList("tst1", "tst2")
        .forEach((String value) -> System.out.println(value));
//block de données possible
Arrays.<String>asList("tst1", "tst2")
        .forEach(value -> {  System.out.println(value); });
        
//Plusieurs parametre (reduce), parenthèse Obligatoire
list.stream()
    .filter((value -> value % 2 != 0))
    .map(value ->  value * 2)
    .distinct()
    .reduce(0, (val1, val2) -> val1 + val2)
                     
                
public void test() {
    int x = 0; //variable locale
    Arrays.asList(1, 2, 3).forEach(value -> x+=value); //erreur !!!!
    //La variable x est considérée final par la lambda.
}
                        
                Choisit les élements si le predicat est vrai
.map(Function< E, R>) → Stream< R>Transforme les élements
.flatMap(Function< E, Stream< R>>) → Stream< R>Applatit l'ensemble des Streams de chaque élement
.skip(), .limit()Saute des élements, reduit le nombre d'élement
.distinct(), .sorted(Comparator< E>)Sans doublon (par rapport à equals), trie
Compte les élements
.forEach(Consumer< E>)Applique le consumer pour chaque élement
.allMatch(Predicate< E>), .anyMatch(Predicate< E>)Vrai si tout les/au moins un élement(s) match
.findAny(), .findFirst() → Optional< E>Trouver un ou le premier, renvoie une posibilité d'élement
.toArray(IntFunction)Crée un tableau ex: .toArray(String[]::new)
.reduce(), collect(Collector) Aggège les éléments en 1 valeur (resp. non-mutable, mutable)