Listing 1: Methoden parallelisieren

public void execute()
{
    List<String> data = retrieveData();
    
    Long value1 = processData1(data);
    Long value2 = processData2(data);
    Long value3 = processData3(data);
    
    String result = calcResult(value1, value2, value3);
    System.out.println("result: " + result);
}

Listing 2: --CompletableFuture

public void execute() throws InterruptedException, ExecutionException
{
    CompletableFuture<List<String>> cFData = 
                     CompletableFuture.supplyAsync(() -> retrieveData());

    // Auswertungen parallel ausführen
    CompletableFuture<Long> cFValue1 =                       cFData.thenApplyAsync(data -> processData1(data));
    CompletableFuture<Long> cFValue2 =                       cFData.thenApplyAsync(data -> processData2(data));
    CompletableFuture<Long> cFValue3 =                       cFData.thenApplyAsync(data -> processData3(data));
         // Einzelergebnisse synchron zusammenführen 
    String result = calcResult(cFValue1.get(),                                 cFValue2.get(), cFValue3.get());
    System.out.println("result: " + result);
}

Listing 3: Timeouts, Exception-Handlung und Fallback-Werte

CompletableFuture<List<String>> cFData =                    CompletableFuture.supplyAsync(() -> retrieveData()).                   exceptionally((throwable) -> Collections.emptyList());

CompletableFuture<Long> cFValue3 = 
                        cFData.thenApplyAsync(data -> processData3(data)).
                               completeOnTimeout(7L, 2, TimeUnit.SECONDS);


Listing 4: ifPresentOrElse()

public static void main(String[] args) throws Exception
{
    // HTTP-2-API + Date and Time API
    HttpClient httpClient =      HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();

    // Date and Time API => Stream mit monatlicher Schrittweite
    LocalDate startDay = LocalDate.of(2019, Month.JANUARY, 1);
    LocalDate endDay = LocalDate.of(2020, Month.MAY, 1);
    Period stepOneMonth = Period.ofMonths(1);

    // DATESUNTIL
    startDay.datesUntil(endDay, stepOneMonth).forEach(localDate -> 
    {
        // TEMPORALADJUSTERS
        LocalDate endOfMonth =                    localDate.with(TemporalAdjusters.lastDayOfMonth());

        // var seit Java 10 und Aufruf mit HTTP/2-API
        var optResponseBody = performGet(httpClient, endOfMonth);

        // OPTIONAL
        optResponseBody.ifPresentOrElse(              (value) -> System.out.println(endOfMonth + " reported " + value),
             () -> System.out.println("No data for " + endOfMonth));
    });
}

private static Optional<String> performGet(HttpClient httpClient,                                             LocalDate desiredDate)
{
    try
    {
        HttpRequest httpRequest =                      HttpRequest.newBuilder().GET().uri(URI.create(         "https://api.exchangeratesapi.io/" + desiredDate + "?symbols=CHF")).         build();

        var response = httpClient.send(httpRequest, BodyHandlers.ofString());
        String responseBody = response.body();

        return Optional.of(responseBody);
    }
    catch (Exception ex)
    {
        // LOG
    }
    return Optional.empty();
}


Listing 5: Wechselkurse

2019-01-31 reported {"rates":{"CHF":1.1409},"base":"EUR","date":"2019-01-31"}
2019-02-28 reported {"rates":{"CHF":1.1335},"base":"EUR","date":"2019-02-28"}
2019-03-31 reported {"rates":{"CHF":1.1181},"base":"EUR","date":"2019-03-29"}
2019-04-30 reported {"rates":{"CHF":1.1437},"base":"EUR","date":"2019-04-30"}
…
2020-02-29 reported {"rates":{"CHF":1.0614},"base":"EUR","date":"2020-02-28"}
2020-03-31 reported {"rates":{"CHF":1.0585},"base":"EUR","date":"2020-03-31"}
2020-04-30 reported {"rates":{"CHF":1.0582},"base":"EUR","date":"2020-04-07"}


Listing 6: Switch Expressions

DayOfWeek day = DayOfWeek.FRIDAY;

int numOfLetters = switch (day)
{
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};


Listing 7: JSON

String jsonObj = """
                 {
                     "name"    : "Mike",
                     "birthday": "1971-02-07",
                     "comment" : "Text blocks are nice!"
                 }
                 """;


Listing 8: Ohne Records

public final class MyPoint
{
    private final int x;
    private final int y;

    public MyPoint(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    @Override 
    public boolean equals(Object o)
    {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        
        MyPoint point = (MyPoint) o;
        return x == point.x && y == point.y;
    }

    @Override 
    public int hashCode()
    {
        return Objects.hash(x, y);
    }

    @Override public String toString()
    {
        return "MyPoint[x=" + x + ", y=" + y + "]";
    }
    
    // lesende Zugriffsmethoden auf x und y
}
