¿Cuál es la diferencia entre 'CompletionStage' y 'CompletableFuture'?

He visto un ejemplo en cada uno de ellos, pero necesito saber exactamente cuál es la diferencia en profundidad, porque a veces creo que puedo usar ambos para obtener el mismo resultado, así que quiero saber para poder elegir el correcto ¿uno?

¿Cuál es el beneficio de usar cada uno de ellos?

Como este ejemplo, ambos son trabajados:

public CompletionStage<Result> getNextQueryUUID() {
    return CompletableFuture.supplyAsync(() -> {
        String nextId = dbRequestService.getNextRequestQueryUUID();
        return ok(nextId);
    }, executor);
}


public CompletableFuture<Result> getNextQueryUUID() {
    return CompletableFuture.supplyAsync(() -> {
        String nextId = dbRequestService.getNextRequestQueryUUID();
        return ok(nextId);
    }, executor);
}

Este ejemplo se ejecuta enPlay framework.

Respuestas a la pregunta(3)

Su respuesta a la pregunta