Java 8 :
Introduction des Lambdas, Streams, Optional, Date/Time API.
Les Functional Interfaces en Java
Java 11 :
var en lambdas, amélioration des String, HttpClient.
Java 17 :
switch avancé, records, sealed classes.
Java 21 :
switch finalisé, virtual threads, sequenced collections, scoped values.
Spring 5 : Introduction de WebFlux, support de Java 8+, programmation réactive.
Spring 6 : Passage à Jakarta EE 9+, amélioration de la sécurité et observabilité.
Spring Boot 2 : Performance accrue, WebFlux, Actuator amélioré.
Spring Boot 3 : Support des Virtual Threads, GraalVM, OpenTelemetry.
Angular 9-12 : Ivy devient le moteur par défaut, améliorations des performances.
Angular 13-15 : Standalone Components, TypeScript 4.5+, simplification de la
configuration.
Angular 16-18 : Signals API, Hydration SSR, nouvelles directives @for et @if.
Java 8 (2014) : Révolution Fonctionnelle
Java 8 a introduit des fonctionnalités majeures qui ont changé la manière d'écrire du code en
Java.
1. Lambda Expressions
Les expressions lambda permettent d'écrire des fonctions anonymes plus concises.
Exemple
// Avant Java 8
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
};
// Avec Java 8 (Lambda)
Comparator<String> comparatorLambda = (s1, s2) -> s1.length() - s2.length();
2. Streams API
Permet de manipuler des collections de données de manière fonctionnelle.
Exemple
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
// Filtrer les noms qui commencent par 'A' et les afficher
names.stream()
.filter(name -> name.startsWith("A"))
.forEach(System.out::println);
3. Default Methods dans les Interfaces
Les interfaces peuvent désormais avoir des méthodes avec implémentation par défaut.
interface Vehicle {
default void print() {
System.out.println("Ceci est un véhicule");
}
}
class Car implements Vehicle {}
public class Main {
public static void main(String[] args) {
new Car().print(); // Affiche : Ceci est un véhicule
}
}
4. Optional
Évite les NullPointerException en encourageant l'utilisation de valeurs optionnelles.
Exemple
Optional<String> optional = Optional.ofNullable(null);
System.out.println(optional.orElse("Valeur par défaut")); // Affiche : Valeur par défaut
5. API Date & Time (java.time)
Nouvelle API de gestion des dates plus robuste.
Exemple
LocalDate today = LocalDate.now();
System.out.println("Aujourd'hui : " + today);
LocalDate nextWeek = today.plusWeeks(1);
System.out.println("Semaine prochaine : " + nextWeek);
Les Functional Interfaces en Java
Une Functional Interface est une interface qui ne contient qu'une seule méthode abstraite. Elle
peut contenir des méthodes default ou static, mais ne doit avoir qu'une seule méthode
abstraite. Ces interfaces sont particulièrement utiles pour la programmation fonctionnelle et sont
souvent utilisées avec les expressions lambda et les références de méthode.
Java fournit plusieurs functional interfaces dans le package java.util.function, comme
Supplier, Consumer, Function, Predicate, BiFunction, BiPredicate, BiConsumer, etc.
1. Exemple avec Function<T, R> et andThen()
L'interface Function<T, R> prend un argument de type T et retourne un résultat de type R.
La méthode andThen(Function<R, V>) permet de chaîner deux fonctions.
✅ Exemple
import java.util.function.Function;
public class FunctionExample {
public static void main(String[] args) {
Function<Integer, Integer> multiplyByTwo = x -> x * 2;
Function<Integer, Integer> addThree = x -> x + 3;
// Combinaison des deux fonctions : d'abord multiplyByTwo puis
addThree
Function<Integer, Integer> combinedFunction =
multiplyByTwo.andThen(addThree);
System.out.println(combinedFunction.apply(5)); // (5 * 2) + 3 = 13
}
}
2. Exemple avec BiFunction<T, U, R> et andThen()
L'interface BiFunction<T, U, R> prend deux arguments (T, U) et retourne un résultat R.
La méthode andThen(Function<R, V>) permet d'appliquer une autre fonction après l'exécution
de la première.
✅ Exemple
import java.util.function.BiFunction;
import java.util.function.Function;
public class BiFunctionExample {
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer> multiply = (a, b) -> a * b;
Function<Integer, String> convertToString = result -> "Résultat: " +
result;
// Chaînage avec andThen : d'abord multiply, puis convertToString
BiFunction<Integer, Integer, String> combined =
multiply.andThen(convertToString);
System.out.println(combined.apply(4, 5)); // Résultat: 20
}
}
3. Exemple avec Supplier<T>
Un Supplier<T> ne prend aucun paramètre et retourne une valeur de type T.
✅ Exemple
import java.util.function.Supplier;
public class SupplierExample {
public static void main(String[] args) {
Supplier<Double> randomSupplier = () -> Math.random();
System.out.println(randomSupplier.get()); // Affiche un nombre
aléatoire
}
}
4. Exemple avec Consumer<T> et andThen()
Un Consumer<T> prend une valeur et n'en retourne aucune. Il est utilisé pour effectuer des
actions sur des objets.
✅ Exemple
import java.util.function.Consumer;
public class ConsumerExample {
public static void main(String[] args) {
Consumer<String> printUpperCase = s ->
System.out.println(s.toUpperCase());
Consumer<String> printLowerCase = s ->
System.out.println(s.toLowerCase());
// Chaînage avec andThen()
Consumer<String> combinedConsumer =
printUpperCase.andThen(printLowerCase);
combinedConsumer.accept("Java Functional Interfaces");
}
}
Sortie :
Nginx
JAVA FUNCTIONAL INTERFACES
java functional interfaces
5. Exemple avec Predicate<T> et or() / and()
Un Predicate<T> prend une valeur et retourne un boolean.
Les méthodes or(), and(), et negate() permettent de combiner plusieurs prédicats.
✅ Exemple
import java.util.function.Predicate;
public class PredicateExample {
public static void main(String[] args) {
Predicate<Integer> isEven = x -> x % 2 == 0;
Predicate<Integer> isPositive = x -> x > 0;
Predicate<Integer> isEvenAndPositive = isEven.and(isPositive);
Predicate<Integer> isEvenOrPositive = isEven.or(isPositive);
System.out.println(isEvenAndPositive.test(4)); // true (4 est pair
et positif)
System.out.println(isEvenAndPositive.test(-4)); // false (-4 est pair
mais pas positif)
System.out.println(isEvenOrPositive.test(-4)); // true (-4 est pair)
System.out.println(isEvenOrPositive.test(3)); // true (3 est
positif)
}
}
✅ Résumé des méthodes principales
Interface Signature de la méthode principale Description
Function<T, R> R apply(T t) Transforme une valeur de T en R
BiFunction<T, U, R> R apply(T t, U u) Transforme deux valeurs (T, U) en R
Consumer<T> void accept(T t) Exécute une action sur T
BiConsumer<T, U> void accept(T t, U u) Exécute une action sur (T, U)
Supplier<T> T get() Retourne une valeur sans paramètre
Predicate<T> boolean test(T t) Teste une condition sur T
Java 11 (2018) : Améliorations et Performance
Java 11 a apporté des améliorations de syntaxe et de nouvelles API.
1. var dans les Lambdas
On peut utiliser var pour déclarer les paramètres d’une expression lambda.
Exemple
BiFunction<Integer, Integer, Integer> sum = (var a, var b) -> a + b;
System.out.println(sum.apply(5, 3)); // Affiche : 8
2. String API améliorée
strip() : Supprime les espaces en début et fin (meilleur que trim()).
lines() : Divise une chaîne en lignes.
repeat(n) : Répète une chaîne n fois.
Exemple
String text = " Bonjour ";
System.out.println(text.strip()); // "Bonjour"
String multiline = "Ligne 1\nLigne 2\nLigne 3";
multiline.lines().forEach(System.out::println); // interface Fonctionel
System.out.println("Java ".repeat(3)); // "Java Java Java "
3. HttpClient
Nouvelle API pour effectuer des requêtes HTTP de manière plus moderne.
Exemple
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Java 17 (2021) : LTS et Simplicité
Java 17 a introduit des améliorations de la syntaxe et des performances.
1. Pattern Matching pour switch (Preview)
Permet d’écrire des switch plus lisibles.
Exemple
Object obj = 123;
String result = switch (obj) {
case Integer i -> "Nombre entier : " + i;
case String s -> "Chaîne : " + s;
default -> "Autre type";
};
System.out.println(result); // Affiche : Nombre entier : 123
2. Records (Simplification des POJO)
Les records permettent de créer des classes immuables sans code boilerplate.
Exemple
record Person(String name, int age) {}
Person person = new Person("Alice", 30);
System.out.println(person.name()); // Affiche : Alice
3. Sealed Classes
Permet de restreindre quelles classes peuvent hériter d’une classe.
Exemple
sealed class Vehicle permits Car, Truck {}
final class Car extends Vehicle {}
final class Truck extends Vehicle {}
Java 21 (2023) : Modernisation et Performance
Java 21 a introduit des améliorations majeures, notamment des fonctionnalités finalisées.
1. Pattern Matching pour switch (Finalisé)
Améliore la lisibilité avec des cas plus précis.
Exemple
static String format(Object obj) {
return switch (obj) {
case Integer i -> "Nombre entier : " + i;
case String s when s.length() > 5 -> "Longue chaîne : " + s;
case null -> "Valeur nulle";
default -> "Autre type";
};
}
System.out.println(format("HelloWorld")); // Affiche : Longue chaîne : HelloWorld
2. Virtual Threads (Performance)
Les virtual threads améliorent la gestion des threads en Java.
Exemple
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
executor.submit(() -> {
System.out.println("Hello depuis un Virtual Thread !");
});
executor.shutdown();
3. Sequenced Collections
Introduit une nouvelle API pour manipuler des collections de manière ordonnée.
Exemple
SequencedSet<Integer> numbers = new LinkedHashSet<>();
numbers.add(1);
numbers.add(2);
numbers.addFirst(0);
numbers.addLast(3);
System.out.println(numbers); // Affiche : [0, 1, 2, 3]
4. Scoped Values (Gestion des Contextes)
Permet de partager des valeurs immuables entre threads de manière efficace.
Exemple
ScopedValue<String> user = ScopedValue.newInstance();
void process() {
ScopedValue.runWhere(user, "Alice", () -> {
System.out.println("Utilisateur : " + user.get());
});
}
process(); // Affiche : Utilisateur : Alice
🌱 Spring 5 (2017)
Spring 5 a introduit des améliorations majeures, notamment la compatibilité avec Java 8+ et le
support réactif.
1. Support de Java 8+ et Java 9
Spring 5 impose Java 8 minimum et apporte une compatibilité avec Java 9+.
Exemple : Utilisation de Optional dans un Service
@Service
public class UserService {
public Optional<User> findUserById(Long id) {
return userRepository.findById(id);
}
}
2. Programmation Réactive avec Spring WebFlux
Spring WebFlux permet de créer des applications réactives, en alternative à Spring MVC.
Exemple : Contrôleur WebFlux
@RestController
public class UserController {
@GetMapping("/users")
public Flux<User> getUsers() {
return userService.getAllUsers(); // Renvoie un Flux réactif
}
}
3. Utilisation de @Nullable et @NonNull
Ajoute une meilleure gestion de la nullabilité.
Exemple
public String sayHello(@Nullable String name) {
return name != null ? "Hello " + name : "Hello Guest!";
}
4. Amélioration du Functional Bean Registration
Possibilité de déclarer des beans via des lambdas.
Exemple
@Configuration
public class AppConfig {
@Bean
public Supplier<String> messageSupplier() {
return () -> "Hello from Spring 5!";
}
}
🚀 Spring 6 (2022)
Spring 6 a introduit le support de Jakarta EE 9+, des améliorations de sécurité et des
performances accrues.
1. Migration vers Jakarta EE 9+
Spring 6 utilise Jakarta EE 9+, ce qui signifie que les packages javax.* sont maintenant
jakarta.*.
Avant (Spring 5)
import javax.servlet.http.HttpServletRequest;
Après (Spring 6)
import jakarta.servlet.http.HttpServletRequest;
2. Amélioration de Spring Security
Support des Password Encoders et meilleure gestion des JWT.
Exemple : Configuration d’un Password Encoder
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
3. Observabilité avec Micrometer
Spring 6 intègre Micrometer pour la télémétrie.
Exemple : Exposition des métriques
@Bean
MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config().commonTags("application", "MyApp");
}
🔥 Spring Boot 2 (2018)
Spring Boot 2 a apporté des améliorations en termes de performances, de sécurité et de
réactivité.
1. Migration vers Spring 5 et Java 8+
Spring Boot 2 repose sur Spring 5 et apporte WebFlux.
2. Meilleure Gestion des Properties
Possibilité d’utiliser @ConfigurationProperties avec des classes POJO.
Exemple
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
// Getters et Setters
}
3. Actuator Amélioré
Ajout de nouvelles métriques et points de terminaison.
Exemple : Activer Actuator
Dans application.properties :
management.endpoints.web.exposure.include=health,info
⚡ Spring Boot 3 (2022)
Spring Boot 3 repose sur Spring 6 et apporte des améliorations majeures.
1. Passage à Jakarta EE
Les applications doivent migrer de javax.* vers jakarta.*.
2. Virtual Threads avec Spring Boot 3.2+
Spring Boot 3.2 prend en charge les Virtual Threads (Loom).
Exemple
@Bean
Executor virtualThreadExecutor() {
return Executors.newVirtualThreadPerTaskExecutor();
}
3. Spring AOT (Ahead-of-Time) Compilation
Optimise Spring pour GraalVM et les images natives.
4. Observabilité avec Micrometer et OpenTelemetry
Spring Boot 3 améliore les logs et les traces distribuées.
Exemple
@Bean
MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config().commonTags("application", "MyApp");
}
ANGULAR
🚀 Angular 9 (Février 2020)
1. Ivy par défaut
Le moteur de rendu Ivy devient le moteur de compilation et de rendu par défaut, améliorant les
performances et la réduction de la taille des bundles.
Exemple : Amélioration de la taille des bundles
Avant Angular 9, les composants inutilisés étaient inclus dans le bundle. Avec Ivy, le tree-
shaking supprime le code inutilisé.
⚡ Angular 10 (Juin 2020)
1. Support amélioré de TypeScript 3.9
Meilleure compatibilité et vérification de types plus stricte.
2. Nouvelle configuration stricte
Un nouveau flag --strict pour générer un projet avec des restrictions TypeScript et Angular
strictes.
ng new my-app --strict
🔥 Angular 11 (Novembre 2020)
1. Webpack 5 et Build plus rapide
Amélioration des builds et réduction du temps de compilation.
2. Mise à jour automatique avec ng update
ng update @angular/core @angular/cli
🚀 Angular 12 (Mai 2021)
1. Abandon de View Engine (Ivy only)
Le moteur View Engine est supprimé, Angular repose uniquement sur Ivy.
2. Support des Webpack 5 et TypeScript 4.2
Meilleure gestion des imports et des performances accrues.
⚡ Angular 13 (Novembre 2021)
1. Suppression de ViewEngine
Tout projet Angular doit utiliser Ivy.
2. Amélioration de la gestion des composants
Les composants n'ont plus besoin d'être déclarés dans les entryComponents.
🔥 Angular 14 (Juin 2022)
1. Standalone Components
Possibilité de créer des composants sans NgModule.
Exemple : Standalone Component
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-hello',
template: `<h1>Hello Angular!</h1>`,
})
export class HelloComponent {}
🚀 Angular 15 (Novembre 2022)
1. Amélioration des Standalone APIs
On peut maintenant charger des routes sans NgModule.
Exemple : Déclaration de routes standalone
const routes: Routes = [
{ path: '', component: HomeComponent },
];
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes)]
});
⚡ Angular 16 (Mai 2023)
1. Signals API
Les Signals permettent une gestion réactive des états sans RxJS.
Exemple : Utilisation de Signals
import { signal } from '@angular/core';
export class CounterComponent {
count = signal(0);
increment() {
this.count.set(this.count() + 1);
}
}
2. Hydration pour SSR
Amélioration du Server Side Rendering (SSR) avec hydration automatique.
🔥 Angular 17 (Novembre 2023)
1. Nouvelle syntaxe de Template ( @for / @if )
Les nouvelles directives structurales simplifient les templates.
Exemple : @for et @if
@Component({
selector: 'app-example',
template: `
@if (users.length > 0) {
<ul>
@for (user of users; track user.id) {
<li>{{ user.name }}</li>
}
</ul>
}
`,
})
export class ExampleComponent {
users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
}
🚀 Angular 18 (Mai 2024 - à venir)
Angular 18 continue d'améliorer la performance et la DX (Developer Experience).
Les Signals deviennent la norme et les Standalone Components sont encore plus optimisés.