Cheatsheet — Java 8 → Java 21

Résumé des apports majeurs par version avec exemples avant/après et problématiques résolues.

Java 8 (2014)

Lambdas & Streams

// Avant
List<String> result = new ArrayList<>();
for (String n : noms) {
    if (n.startsWith("C")) result.add(n);
}

// Après
List<String> result = noms.stream()
                          .filter(n -> n.startsWith("C"))
                          .toList();

Problématique résolue : rendre le code plus concis, déclaratif et parallélisable.

Optional

// Avant
if (user != null) {
    sendEmail(user);
}

// Après
Optional.ofNullable(user).ifPresent(u -> sendEmail(u));

Problématique résolue : réduire les NullPointerException.

API Date/Time (java.time)

// Avant
Date d = new Date();
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_MONTH, 7);

// Après
LocalDate now = LocalDate.now();
LocalDate nextWeek = now.plusWeeks(1);

Problématique résolue : remplacer une API peu intuitive par une API claire et immuable.


Java 9 (2017)

Modules (Jigsaw)

// Avant : pas de modularité stricte
// Tout était accessible dans le classpath.

// Après
module com.monapp {
    requires java.sql;
    exports com.monapp.service;
}

Problématique résolue : meilleure encapsulation et modularité.

Collections immuables

// Avant
List<String> fixed = Collections.unmodifiableList(Arrays.asList("a","b","c"));

// Après
List<String> fixed = List.of("a","b","c");

Problématique résolue : construction simple et sûre de collections immuables.


Java 10 (2018)

var

// Avant
Map<String, List<Integer>> map = new HashMap<>();

// Après
var map = new HashMap<String, List<Integer>>();

Problématique résolue : réduire le bruit syntaxique.


Java 11 (2018 – LTS)

HTTP Client

// Avant
URL url = new URL("https://api");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");

// Après
HttpClient client = HttpClient.newHttpClient();
HttpRequest req = HttpRequest.newBuilder().uri(URI.create("https://api")).build();
HttpResponse<String> res = client.send(req, HttpResponse.BodyHandlers.ofString());

Problématique résolue : API moderne et support de HTTP/2.

String API

// Avant
"  hi ".trim(); // mais supprime seulement les espaces

// Après
"  hi ".strip(); // supprime tous les blancs Unicode

Problématique résolue : utilitaires String plus puissants.


Java 12 (2019)

Switch expression (preview)

// Avant
String type;
switch(day) {
    case 1: case 7: type = "Weekend"; break;
    default: type = "Weekday";
}

// Après
String type = switch(day) {
    case 1, 7 -> "Weekend";
    default -> "Weekday";
};

Problématique résolue : switch concis et sans erreurs de break.


Java 13 (2019)

Text blocks (preview)

// Avant
String json = "{\n  \"name\": \"Alice\"\n}";

// Après
String json = """
{
  "name": "Alice"
}
""";

Problématique résolue : littéraux multilignes sans concaténation.


Java 14 (2020)

Records

// Avant
class Person {
    private final String name;
    private final int age;
    Person(String n, int a) { this.name=n; this.age=a; }
    public String name() { return name; }
    public int age() { return age; }
}

// Après
record Person(String name, int age) {}

Problématique résolue : suppression du boilerplate.

Pattern matching instanceof

// Avant
if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.length());
}

// Après
if (obj instanceof String s) {
    System.out.println(s.length());
}

Problématique résolue : éviter les casts répétitifs.


Java 15 (2020)

Sealed classes

// Avant : hiérarchie non contrôlée
interface Shape {}
class Circle implements Shape {}
class Square implements Shape {}

// Après
sealed interface Shape permits Circle, Square {}
final class Circle implements Shape {}
final class Square implements Shape {}

Problématique résolue : contrôle des sous-types autorisés.


Java 16 (2021)

Records et pattern matching stabilisés ➡️ Production-ready, mêmes exemples que Java 14.

jpackage

# Avant : outils tiers (Launch4j, InnoSetup...)
# Après :
jpackage --name MonApp --input out/ --main-jar monapp.jar

Problématique résolue : création d’installateurs natifs.


Java 17 (2021 – LTS)

Pattern matching switch

// Avant
if (o instanceof String) return "String";
else if (o instanceof Integer) return "int";

// Après
return switch(o) {
    case String s -> "String";
    case Integer i -> "int";
    default -> "other";
};

Problématique résolue : switch exhaustif et typé.


Java 18 (2022)

Mini serveur web

# Avant : dépendance externe (Jetty, Tomcat...)
# Après :
jwebserver --port 8080 --directory .

Problématique résolue : serveur léger intégré pour dev/test.


Java 19 (2022)

Virtual Threads (preview)

// Avant : threads classiques lourds
new Thread(() -> System.out.println("Hi")).start();

// Après
Thread.startVirtualThread(() -> System.out.println("Hi"));

Problématique résolue : millions de threads possibles.


Java 20 (2023)

Record patterns (preview)

// Avant
if (p instanceof Point) {
    Point pt = (Point) p;
    System.out.println(pt.x()+", "+pt.y());
}

// Après
if (p instanceof Point(int x, int y)) {
    System.out.println(x+", "+y);
}

Problématique résolue : destructuration claire.


Java 21 (2023 – LTS)

Virtual Threads (finalisé)

// Avant
ExecutorService pool = Executors.newFixedThreadPool(10);

// Après
try (var exec = Executors.newVirtualThreadPerTaskExecutor()) {
    exec.submit(() -> Thread.sleep(1000));
}

Problématique résolue : simplifier la concurrence massivement.

String Templates (preview)

// Avant
String msg = "Name: " + name + ", Age: " + age;

// Après
String msg = STR."Name: \{name}, Age: \{age}";

Problématique résolue : interpolation lisible et sûre.

Record patterns + switch ➡️ mêmes améliorations que Java 20, finalisées.


Synthèse

  • Java 8 : lambdas, streams, date/time moderne.
  • Java 9–11 : modularité, API modernes (HTTP client).
  • Java 12–16 : switch expressions, records, text blocks.
  • Java 17 (LTS) : pattern matching, sealed classes.
  • Java 19–21 : virtual threads, record patterns, string templates — modernisation de la concurrence et expressivité du langage.