Łączenie za pomocą thenApply i thenCompose
Przekształcaj wyniki przez thenApply i spłaszczaj asynchroniczne kroki przez thenCompose, aby unikać zagnieżdżonych future.
Łączenie za pomocą thenApply i thenCompose to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.
thenApply: Przekształcanie wyniku
thenApply(Function) stosuje synchroniczną funkcję do wyniku ukończonego future i zwraca nowy future z przekształconym typem. Nie uruchamia nowego zadania asynchronicznego.
CompletableFuture<String> nameFuture = CompletableFuture
.supplyAsync(() -> 42L) // CF<Long>
.thenApply(id -> "User#" + id); // CF<String>
System.out.println(nameFuture.join()); // "User#42"thenApplyAsync: Przekształcanie w wątku
thenApplyAsync uruchamia funkcję przekształcającą w puli ForkJoinPool lub w puli przekazanego executora, natychmiast zwalniając wątek kończący obliczenie.
CompletableFuture<String> result = fetchUserAsync()
.thenApplyAsync(user -> serialize(user)); // runs on pool threadthenAccept: Przetwarzanie bez zwracania wyniku
thenAccept(Consumer) przetwarza wynik, ale zwraca CompletableFuture<Void>. Należy używać go jako ostatniego kroku potoku, gdy nie trzeba przekazywać dalej wartości.
fetchUserAsync()
.thenApply(User::getName)
.thenAccept(name -> System.out.println("Hello, " + name));thenRun: Uruchamianie po ukończeniu
thenRun(Runnable) uruchamia zadanie po ukończeniu future, ignorując wynik. Dobrze nadaje się do zamykania zasobów lub wywoływania efektów ubocznych.
downloadFileAsync(url)
.thenRun(() -> System.out.println("Download complete"));Łączenie wielu wywołań thenApply
Wiele wywołań thenApply tworzy potok. Każdy krok otrzymuje wynik poprzedniego kroku.
CompletableFuture<Double> result = CompletableFuture
.supplyAsync(() -> " 42.5 ")
.thenApply(String::trim)
.thenApply(Double::parseDouble)
.thenApply(d -> d * 1.21); // apply 21% VAT
System.out.println(result.join()); // 51.425thenCompose: Spłaszczanie zagnieżdżonych future
thenCompose(Function<T, CompletionStage<U>>) działa podobnie do flatMap dla future. Zapobiega powstaniu CompletableFuture<CompletableFuture<T>>, spłaszczając zagnieżdżony future.
// Wrong with thenApply — returns CF<CF<Order>>:
CompletableFuture<CompletableFuture<Order>> nested =
fetchUser(id).thenApply(u -> fetchLatestOrder(u.getId()));
// Correct with thenCompose — returns CF<Order>:
CompletableFuture<Order> flat =
fetchUser(id).thenCompose(u -> fetchLatestOrder(u.getId()));thenCompose dla sekwencyjnych wywołań asynchronicznych
Należy używać thenCompose, gdy każdy asynchroniczny krok zależy od wyniku poprzedniego — dzięki temu kroki są wykonywane sekwencyjnie i zależą od wyników.
fetchUser(userId)
.thenCompose(user -> fetchOrders(user.getId()))
.thenCompose(orders -> computeTotal(orders))
.thenAccept(total -> System.out.println("Total: " + total));thenApply a thenCompose
thenApply: odwzorowuje T -> U (synchroniczne przekształcenie). thenCompose: odwzorowuje T -> CompletableFuture<U> i spłaszcza wynik. Należy używać compose, gdy następny krok również jest asynchroniczny.
Obsługa błędów pośrednich za pomocą handle
handle(BiFunction<T, Throwable, U>) jest wywoływane niezależnie od tego, czy future został ukończony pomyślnie, czy wyjątkowo, co pozwala odzyskać sprawność lub przekształcić błędy w środku potoku.
fetchUser(id)
.thenApply(User::getProfile)
.handle((profile, ex) -> {
if (ex != null) return Profile.empty(); // recover
return profile;
})
.thenAccept(System.out::println);whenComplete: Efekt uboczny po dowolnym wyniku
whenComplete(BiConsumer) jest wywoływane po ukończeniu obliczenia (pomyślnym lub wyjątkowym) w celu rejestrowania informacji lub czyszczenia zasobów. W przeciwieństwie do handle nie zmienia wyniku.
fetchAsync()
.whenComplete((result, ex) -> {
if (ex != null) log.error("Failed", ex);
else log.info("Result: " + result);
});Przykład potoku bez blokowania
Należy utworzyć w pełni nieblokujący potok: pobrać użytkownika, pobrać jego zamówienia i obliczyć podsumowanie — wszystkie kroki są wykonywane asynchronicznie, a każdy zależy od poprzedniego.
CompletableFuture<String> summary =
fetchUser(userId)
.thenCompose(u -> fetchOrders(u.getId()))
.thenApply(orders -> orders.size() + " orders")
.exceptionally(ex -> "Error: " + ex.getMessage());
System.out.println(summary.join());Szybkie sprawdzenie
Kiedy należy użyć thenCompose zamiast thenApply?
Podsumowanie
thenApply przekształca wartości synchroniczne w potoku. thenCompose łączy kroki asynchroniczne (działa jak flatMap dla future). handle / whenComplete dodają obsługę błędów i efekty uboczne. Dla czytelności należy budować potoki od lewej do prawej.
Często zadawane pytania
Czy lekcja „Łączenie za pomocą thenApply i thenCompose” jest bezpłatna?
Tak — pełny tekst „Łączenie za pomocą thenApply i thenCompose” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Łączenie za pomocą thenApply i thenCompose”?
Przekształcaj wyniki przez thenApply i spłaszczaj asynchroniczne kroki przez thenCompose, aby unikać zagnieżdżonych future. Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Java Academy?
Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Łączenie za pomocą thenApply i thenCompose”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?
Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Tworzenie i uzupełnianie CompletableFuture
- Łączenie za pomocą thenApply i thenCompose
- Łączenie future: allOf i anyOf
- Obsługa błędów i asynchroniczny potok HTTP