Overview
Result<F, S> is a sealed interface that represents either a successful outcome (Success<F, S>) or a failure (Failure<F, S>). It provides a functional approach to error handling without exceptions.
Package: com.softwarearchetypes.common
Source: /common/src/main/java/com/softwarearchetypes/common/Result.java:14
Type Parameters
The type of the failure value
The type of the success value
Creating Results
success
static <F, S> Result<F, S> success(S value)
Creates a successful Result containing the provided value.
The success value to wrap
A Result in success state
Example:
Result<String, Integer> result = Result.success(42);
assert result.success(); // true
assert result.getSuccess() == 42;
failure
static <F, S> Result<F, S> failure(F value)
Creates a failed Result containing the provided failure value.
The failure value to wrap
A Result in failure state
Example:
Result<String, Integer> result = Result.failure("Error occurred");
assert result.failure(); // true
assert result.getFailure().equals("Error occurred");
State Checking
success
default boolean success()
Checks if this Result is in success state.
true if success, false if failure
failure
default boolean failure()
Checks if this Result is in failure state.
true if failure, false if success
getSuccess
Extracts the success value.
Throws: IllegalStateException if called on a failure Result.
getFailure
Extracts the failure value.
Throws: IllegalStateException if called on a success Result.
default <R> Result<F, R> map(Function<? super S, ? extends R> mapper)
Transforms the success value if present, otherwise returns the failure unchanged.
mapper
Function<? super S, ? extends R>
required
Function to transform the success value. Must not be null.
Result with transformed success value, or original failure
Example:
Result<String, Integer> result = Result.<String, Integer>success(10)
.map(val -> "Value: " + (val * 2));
assert result.getSuccess().equals("Value: 20");
mapFailure
default <L> Result<L, S> mapFailure(Function<? super F, ? extends L> mapper)
Transforms the failure value if present, otherwise returns the success unchanged.
mapper
Function<? super F, ? extends L>
required
Function to transform the failure value. Must not be null.
Result with transformed failure value, or original success
Example:
Result<String, Integer> result = Result.<Integer, Integer>failure(404)
.mapFailure(code -> "Error " + code + ": Not Found");
assert result.getFailure().equals("Error 404: Not Found");
default <L, R> Result<L, R> biMap(
Function<? super S, ? extends R> successMapper,
Function<? super F, ? extends L> failureMapper
)
Transforms both success and failure values.
successMapper
Function<? super S, ? extends R>
required
Function to transform the success value. Must not be null.
failureMapper
Function<? super F, ? extends L>
required
Function to transform the failure value. Must not be null.
Result with transformed value
Example:
Result<Integer, Integer> result = Result.success(1);
Result<String, String> mapped = result.biMap(
val -> String.valueOf(val * 2),
val -> ""
);
assert mapped.getSuccess().equals("2");
flatMap
default <R> Result<F, R> flatMap(Function<S, Result<F, R>> mapping)
Chains Result-producing operations. If this Result is successful, applies the mapping function. If this Result is a failure, returns the failure unchanged.
mapping
Function<S, Result<F, R>>
required
Function that returns a new Result. Must not be null.
Result from the mapping function, or original failure
Example:
Result<String, Integer> result = Result.<String, Integer>success(5)
.flatMap(val -> Result.success(val * 2));
assert result.getSuccess() == 10;
// With failure
Result<String, Integer> failed = Result.<String, Integer>success(5)
.flatMap(val -> Result.failure("Validation failed"));
assert failed.failure();
Side Effects
default Result<F, S> peek(
Consumer<? super S> successConsumer,
Consumer<? super F> failureConsumer
)
Executes a side effect based on the Result state, then returns the Result unchanged.
successConsumer
Consumer<? super S>
required
Consumer to execute on success. Must not be null.
failureConsumer
Consumer<? super F>
required
Consumer to execute on failure. Must not be null.
peekSuccess
default Result<F, S> peekSuccess(Consumer<? super S> successConsumer)
Executes a side effect only if the Result is successful.
successConsumer
Consumer<? super S>
required
Consumer to execute on success. Must not be null.
peekFailure
default Result<F, S> peekFailure(Consumer<? super F> failureConsumer)
Executes a side effect only if the Result is a failure.
failureConsumer
Consumer<? super F>
required
Consumer to execute on failure. Must not be null.
Folding and Combining
default <U> U fold(
Function<? super F, ? extends U> leftMapper,
Function<? super S, ? extends U> rightMapper
)
Reduces the Result to a single value by applying one of two functions.
leftMapper
Function<? super F, ? extends U>
required
Function to apply to failure value. Must not be null.
rightMapper
Function<? super S, ? extends U>
required
Function to apply to success value. Must not be null.
The result of applying the appropriate mapper
Example:
Integer result = Result.<String, Integer>success(10)
.fold(error -> -1, val -> val * 3);
assert result == 30;
Integer failureResult = Result.<String, Integer>failure("Error")
.fold(String::length, val -> val * 3);
assert failureResult == 5;
ifSuccessOrElse
default <R> R ifSuccessOrElse(
Function<S, R> successMapping,
Function<F, R> failureMapping
)
Applies one of two mapping functions based on the Result state.
Function to apply on success. Must not be null.
Function to apply on failure. Must not be null.
The result of applying the appropriate mapping function
combine
default <FAILURE, SUCCESS> Result<FAILURE, SUCCESS> combine(
Result<F, S> secondResult,
BiFunction<F, F, FAILURE> failureCombiner,
BiFunction<S, S, SUCCESS> successCombiner
)
Combines two Results using the appropriate combiner function.
The Result to combine with. Must not be null.
failureCombiner
BiFunction<F, F, FAILURE>
required
Function to combine failure values. Must not be null.
successCombiner
BiFunction<S, S, SUCCESS>
required
Function to combine success values. Must not be null.
Example:
Result<Integer, Integer> first = Result.success(5);
Result<Integer, Integer> second = Result.success(10);
Result<Integer, Integer> combined = first.combine(
second,
(val1, val2) -> val1 - val2,
Integer::sum
);
assert combined.getSuccess() == 15;
Composite Results
composite
static <F, S> CompositeResult<F, S> composite()
Creates an empty composite Result accumulator backed by a List. Use with accumulate() to progressively build up a Result containing multiple values.
CompositeResult with empty list
compositeSet
static <F, S> CompositeSetResult<F, S> compositeSet()
Creates an empty composite Result accumulator backed by a Set. Use with accumulate() to progressively build up a Result containing multiple unique values.
CompositeSetResult with empty set
CompositeResult
Helper class for accumulating multiple Results into a List with fail-fast semantics.
accumulate
public CompositeResult<F, S> accumulate(Result<F, S> newResult)
Accumulates a new Result into this composite. If already failed, returns the existing failure. If new Result fails, returns new failure. If both succeed, adds the new value to the list.
The Result to accumulate. Must not be null.
CompositeResult with accumulated values or failure
Example:
Result<String, List<Integer>> result = Result.<String, Integer>composite()
.accumulate(Result.success(1))
.accumulate(Result.success(2))
.accumulate(Result.success(3))
.toResult();
assert result.success();
assert result.getSuccess().equals(List.of(1, 2, 3));
// Fail-fast behavior
Result<String, List<Integer>> failed = Result.<String, Integer>composite()
.accumulate(Result.success(1))
.accumulate(Result.failure("Error occurred"))
.accumulate(Result.success(3))
.toResult();
assert failed.failure();
assert failed.getFailure().equals("Error occurred");
success
Checks if this composite is in success state.
true if success, false if failure
failure
Checks if this composite is in failure state.
true if failure, false if success
toResult
public Result<F, List<S>> toResult()
Extracts the final Result.
Result containing either a list of all successes or the first failure
CompositeSetResult
Helper class for accumulating multiple Results into a Set with fail-fast semantics. Automatically removes duplicates.
accumulate
public CompositeSetResult<F, S> accumulate(Result<F, S> newResult)
Accumulates a new Result into this composite. If already failed, returns the existing failure. If new Result fails, returns new failure. If both succeed, adds the new value to the set.
The Result to accumulate. Must not be null.
CompositeSetResult with accumulated values or failure
Example:
Result<String, Set<Integer>> result = Result.<String, Integer>compositeSet()
.accumulate(Result.success(1))
.accumulate(Result.success(2))
.accumulate(Result.success(1)) // Duplicate removed
.accumulate(Result.success(3))
.toResult();
assert result.success();
assert result.getSuccess().equals(Set.of(1, 2, 3));
success
Checks if this composite is in success state.
true if success, false if failure
failure
Checks if this composite is in failure state.
true if failure, false if success
toResult
public Result<F, Set<S>> toResult()
Extracts the final Result.
Result containing either a set of all successes or the first failure