Table des matières

Nouveautés de Java 8

Les lambdas expressions

Soit le tableau d’instance de la classe Personne (prénom, nom, age) suivant :

List<Personne> personnes = Arrays.asList(new Personne("Pierre", "Durand", 20), 
                        new Personne("Marie", "Durand", 14),
                        new Personne("Albert", "Martin", 12));

Si la classe Personne redéfini equal et hashcode en fonction du nom et du prénom et que l’on souhaite trier le tableau par âge, il faut définir une classe qui implante l’interface Comparator<Personne> ou mieux utiliser une classe anonyme :

Collections.sort(personnes, new Comparator<Personne>() {
            @Override
            public int compare(Personne o1, Personne o2) {
                return o1.getAge() - o2.getAge();
            }
        });

A partir de Java 8 on peut utiliser des lambda expressions. Elles peuvent être vues comme des classes anonymes ayant une seule méthode dont le type de retour est inféré. Les type des paramètres peuvent aussi être inférés.

Une lambda est composée :

Collections.sort(personnes, (o1, o2) -> o1.getPrenom().compareTo(o2.getPrenom()));

Les interfaces fonctionnelles

Java 8 définit le concept d’interfaces fonctionnelles (elles ont extactement une méthode). Elle permet de manipuler des lambda expressions ou des références vers des méthodes. Une interface peut être définie comme fonctionnelle avec l’annotation @FunctionalInterface. Un ensemble d’interface classiques est proposé dans le JDK :

Function<String, String> at = (name) -> {
   return "@" + name;
};
for (Personne p : personnes) System.out.println(at.apply(p.getNom()));
Supplier<List> listFactory = ArrayList::new;
System.out.println("list factory : "+(listFactory.get() instanceof List));
Consumer<String> println = System.out::println;
println.accept("Consumer say Hello");

Première application

Retrouver des personnes avec un filtre.

En utilisant une classe générique pour la recherche :

public class Processor<T> {
    public List<T> find(Iterable<T> iterable, Predicate<T> predicate) {
        List<T> list = new ArrayList<>();
        for (T t : iterable)
            if (predicate.test(t))
                list.add(t);
        return list;
    }
}
 
Processor<Personne> personneProcessor = new Processor<>();
 
//avec une classe anonyme pour le critère
System.out.println(personneProcessor.find(personnes,
                new Predicate<Personne>() {
                    @Override
                    public boolean test(Personne p) {
                        return p.getNom().equals("Durand")
                                && p.getAge() >= 18
                                && p.getAge() <= 25;
                    }
                }));        

avec une lambda expression

        System.out.println(personneProcessor.find(personnes,
                p -> p.getNom().equals("Durand")
                        && p.getAge() >= 10
                        && p.getAge() <= 15
        ));

Stream

Un stream permet de représenter une séquence d’objets qui peut supporter l’exécution parallèle. La construction de stream peut être “lazzy”.

Un stream peut être créé au dessus d’une collection

List<Personne> personnes = new ArrayList<>();
personnes.add(new Personne("Pierre", "Durand", 20));
personnes.add(new Personne("Marie", "Durand", 14));
personnes.add(new Personne("Albert", "Martin", 12));
 
personnes.stream(); //Returns a sequential Stream with the collection as its source.
personnes.parallelStream(); //Returns a possibly parallel Stream with the collection as its source.

Un stream peut être parcours avec un foreach qui permet d’appliquer une fonction sur chaque élément au fur et à mesure de leur production.

personnes.stream().forEach(System.out::println);

D’autre classe produisent des Stream comme les fichiers. Noter le getResource pour obtenir le chemin absolu.

String filename = this.getClass().class.getResource("/test.txt").getFile();
try (FileReader fileReader = new FileReader(filename);
  BufferedReader br = new BufferedReader(fileReader)) {
  br.lines().forEach(System.out::println);
}
try (Stream stream = Files.lines(Paths.get(filename))) {
            stream.forEach(System.out::println);
}

Il existe des versions plus performantes pour les primitifs IntStream, DoubleStream, et LongStream.

Un stream peut aussi être filtré.

personnes.stream().filter(p -> p.getAge() > 18).forEach(System.out::println);

Et il permet d’utiliser le modèle map/reduce.

double ageMoyen = personnes.parallelStream().mapToInt(Personne::getAge).average().getAsDouble();
System.out.println(ageMoyen);

Javascript avec Nashorn

ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("nashorn");
 
engine.eval("function pers(p,n) { return {nom:n, prenom:p} }");
engine.eval("print(JSON.stringify(pers('Pierre', 'Durand')))");

Optionnal

Objet qui peut contenir ou non une valeur null. Le but faciliter le traitement des null pointer exceptions.

—- dataentry page —- type : Howto technologie_tags : Java, Java8 theme_tags : POO