CtrlK
BlogDocsLog inGet started
Tessl Logo

martinfrancois/java-optionals

Help AI coding agents use Java Optional well in new code and cleanups, without replacing one antipattern with another.

100

2.08x
Quality

100%

Does it follow best practices?

Impact

100%

2.08x

Average score across 4 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

java-optional-api.mdskills/java-optionals/references/

Java Optional-Family API Compatibility

Always infer the project Java baseline before choosing APIs. Check pom.xml, Maven compiler settings, Gradle toolchains, sourceCompatibility, targetCompatibility, .github/workflows/*, Dockerfile, .sdkmanrc, .java-version, and project docs.

If the baseline is unclear, prefer Java 8-compatible Optional code or state the assumption explicitly. Don't use newer APIs just because the current JDK supports them.

Optional Family

API or featureMinimum JavaNotes
Optional<T>8Value-based class, mainly useful as a return type for possible absence.
Optional.empty()8Don't compare to Optional.empty() by identity.
Optional.of(T)8Rejects null.
Optional.ofNullable(T)8Boundary conversion from nullable value.
Optional.get()8Discouraged for ordinary flow; prefer value-binding operations or orElseThrow.
Optional.isPresent()8Predicate-only use can be fine; avoid presence-check plus get() value reopening.
Optional.ifPresent(Consumer)8Side-effect terminal for present values.
Optional.filter(Predicate)8Keep only matching present values.
Optional.map(Function)8Transform a present value.
Optional.flatMap(Function<T, Optional<U>>)8Chain Optional-returning lookups.
Optional.orElse(T)8Fallback expression is evaluated before the call; use only when cheap and side-effect free.
Optional.orElseGet(Supplier)8Lazy fallback; prefer for non-trivial, stateful, IO, or side-effecting fallback work.
Optional.orElseThrow(Supplier)8Absence-as-error with explicit exception supplier.
Optional.ifPresentOrElse(Consumer, Runnable)9Present and empty side-effect branches.
Optional.or(Supplier<Optional<T>>)9Lazy Optional-to-Optional fallback chain.
Optional.stream()9Flatten Stream<Optional<T>> with flatMap(Optional::stream).
no-arg Optional.orElseThrow()10Throws NoSuchElementException; clearer than get() when absence should throw.
Optional.isEmpty()11Empty predicate; avoid isEmpty() plus later value reopening.
OptionalInt, OptionalLong, OptionalDouble8Primitive Optional classes; don't box only to reuse generic Optional examples.
primitive empty, of, getAsInt, getAsLong, getAsDouble8Prefer safer terminals to getAs* for ordinary absence-safe value flow.
primitive isPresent, ifPresent8Uses primitive consumers.
primitive orElse, orElseGet, orElseThrow(Supplier)8Uses primitive values and suppliers.
primitive ifPresentOrElse9Present and empty branches without boxing.
primitive stream()9Produces IntStream, LongStream, or DoubleStream.
no-arg primitive orElseThrow()10Java 10+.
primitive isEmpty()11Java 11+.

No OptionalBoolean exists in the JDK. Use Optional<Boolean> only when absence is semantically different from false; don't collapse absent to false unless the domain says to.

Primitive Optional classes aren't drop-in replacements for Optional<T>. They don't have the same map, flatMap, filter, or, or ofNullable API surface. Use their primitive methods and streams deliberately.

Stream And Collector APIs Returning Optional Values

API or featureMinimum JavaNotes
Stream.findFirst, Stream.findAny8Return Optional<T>; preserve findFirst when encounter order matters.
Stream.min, Stream.max, Stream.reduce(BinaryOperator)8Return Optional<T>.
IntStream.findFirst, findAny, min, max, reduce(IntBinaryOperator)8Return OptionalInt.
LongStream.findFirst, findAny, min, max, reduce(LongBinaryOperator)8Return OptionalLong.
DoubleStream.findFirst, findAny, min, max, reduce(DoubleBinaryOperator)8Return OptionalDouble.
primitive stream average()8Returns OptionalDouble.
Collectors.minBy, Collectors.maxBy, Collectors.reducing(BinaryOperator)8Collectors whose result is Optional<T>.
Stream.ofNullable(T)9Nullable-to-stream bridge; useful at boundaries, not a replacement for Optional everywhere.
Collectors.flatMapping9Can flatten Optional.stream() downstream on Java 9+.

When flattening streams of primitive optionals on Java 9+, use primitive stream bridges: flatMapToInt(OptionalInt::stream), flatMapToLong(OptionalLong::stream), and flatMapToDouble(OptionalDouble::stream).

Adjacent APIs Used In Examples

API or featureMinimum JavaNotes
List.of, Set.of, Map.of9Adjacent examples only; not Optional-specific.
List.copyOf, Set.copyOf, Map.copyOf10Adjacent examples only; not Optional-specific.
Stream.mapMulti and primitive mapMulti variants16Adjacent stream-heavy alternative in some code.
Stream.toList()16Returns an unmodifiable list. It isn't a drop-in replacement for Collectors.toList() when later code mutates the list. Don't use in Java 8-15 examples.
records16Adjacent examples only.
SequencedCollection, List.getFirst(), List.getLast(), List.reversed()21Don't use in generic examples unless Java 21+ is stated.
Stream.gather(Gatherer)24Adjacent stream extension point; don't use for Optional cleanup unless the project baseline supports it and it is clearly simpler.
List.ofLazy(int, IntFunction)26 previewAdjacent only; requires preview features, so don't use in generic examples.
Java 24, 25, and 26 Optional-family additionsnone foundChecked Java 26 Optional-family Javadocs; no new Optional-family methods were found after Java 11.

Collection Javadocs also use the phrase "optional operation". That means a collection operation may throw UnsupportedOperationException; it isn't the java.util.Optional API this skill teaches.

When using APIs outside this table, or when the project baseline is unclear, inspect the relevant Javadocs and build files first.

README.md

tile.json