Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
NotificationsYou must be signed in to change notification settings

finn-no/lambda-companion

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 

Repository files navigation

This project is no longer being maintained, and its usage should be replaced with Vavr (http://www.vavr.io)

Purpose

This project adds some concepts that didn't ship with java 8 lambda project like Either<L,R> or Pair<L,R> etc...

Include from maven

<dependency>    <groupId>no.finn.lambda</groupId>    <artifactId>lambda-companion</artifactId>    <version>0.27</version></dependency>

Either cheatsheet

Why Either?

TheEither class provides a way to enforce failure handling in the same fashion asOptional is a way to enforcenull values handling.

How do I use an Either?

Convention dictates thatLeft is used for failure path andRight is used for success / happy path.

How do I instantiate an Either?

For a failure:

final Either<String, String> var = Either.left("My failure text");

For a success:

final Either<String, String> var = Either.right("My text");

How can I access the Right value?

There is no way to directly access the value inside anEither in the same way asOptional.get().This is made on purpose to avoid code in the style ofif(either.isRight()) { either.getRight(); } which promotes not handling the failure cases (left side).

final Either<String, String> var = ...;final String myValue = either.fold(failure -> handleFailure(failure), Function.identity())

How can I transform the value on only one side?

For theLeft side:

final Either<String, String> var = ...;final Either<Integer, String> transformed = var.left().map(Integer::valueOf);

For theRight side:

final Either<String, String> var = ...;final Either<String, Integer> transformed = var.right().map(Integer::valueOf);

How can I log the failure before transforming it to a default value?

final Logger LOGGER = ...;final Either<Exception, String> either = ...;  final String myValue = either.left().peek(LOGGER::warn)                             .fold(failure -> handleFailure(failure), Function.identity());

I have several Either, how can I log the failures of all of them?

final Logger LOGGER = ...;final Either<Exception, String> either1 = ...;final Either<Exception, String> either2 = ...;final Either<Exception, String> either3 = ...;  Arrays.asList(either1, either2, either3).stream().forEach(either -> either.forEach(LOGGER::warn));

How can I conditionally chain functions on the happy path?

private final Either<Exception, String> getUserInput() {   ...}  private final Either<Exception, Integer> processUserInput(final String userInput) {   ...}  private final Either<Exception, Integer> saveUserInput(final Integer userInput) {   ...}  // processUserInput() only gets executed if getUserInput() succeeded, and saveUserInput() only gets executed if processUserInput() succeededfinal Either<Exception, Integer> chained = getUserInput().joinRight(this::processUserInput).joinRight(this::saveUserInput);

How can I combine several Either to use all of their Right values at once?

private final Integer processValues(final String val1, final String val2, final String val3) {   ...}  final Either<Exception, String> either1 = ...;final Either<Exception, String> either2 = ...;final Either<Exception, String> either3 = ...;Either<Exception, Integer> result = either1.joinRight(val1 -> either2.joinRight(val2 -> either3.right().map(val3 -> processValues(val1, val2, val3))));

StreamableOptional cheatsheet

Why StreamableOptional

It happens (rather often) to end with aStream containingOptional-s and to be willing to only retainPresent instances.

In Java 8 there are 2 options:

  • the bad: filtering withisPresent() and unwrapping values withget():stream().filter(Optional::isPresent).map(Optional::get)
  • and the ugly: flat-mappingOptional values toStream of one or no value:stream().flatMap(opt -> opt.map(Stream::of).orElseGet(Optional::empty))

StreamableOptional is a cleaner shorthand for the second solution above (provided that you useStreamableOptional insteadofOptional ):stream.flatMap(StreamableOptional::stream).

How do I retain only present instances

Arrays.asList(StreamableOptional.of(1), StreamableOptional.empty(), StreamableOptional.of(3))  .stream()  .flatMap(StreamableOptional::stream)  .forEach(System.out::println);  // yields :// 1// 2

I already have a stream of traditional Java 8 Optional, how does that help me?

It might not be the ideal setup, however you still have two possibilities:

  • try to replace usages ofOptional withStreamableOptional upstream of your code if you can;
  • else :stream.map(StreamableOptional::ofOptional).flatMap(StreamableOptional::stream) orstream.map(opt -> StreamableOptional.ofOptional(opt).stream())

How do I get back a traditional Java 8 Optional?

This might indicate a code smell since:

  • you probably usedStreamableOptional to flatMap values into aStream (and thus have no more use for aStreamableOptional)
  • you can use the same operations onStreamableOptional as onOptional

However, this case can happen when you interact with an API that requires anOptional. Then simply use thetoOptional() method.

public apiMethodRequiringAnOptional(Optional<Whatever> maybe);  // call itapiMethodRequiringAnOptional(myStreamableOptional.toOptional());

Try cheatsheet

Why Try?

TheTry class provides convenient ways to handle computations which might fail.

UnlikeEither it is right-biased,simplifying the use of familiar higher order functions such as map, flatMap and forEach.

In proper functional languages,Try is a monad where asEither is not, (but this implementation does not satisfy the monadic lawsbecause of how flatMap borrows inspiration from its counterpart injava.util.Optional)

Warning: Do not useTry onAutoclosable resources and expect them to close (try-with-resources) -Try does not close resources!

An example of using Try

private void playWithTry() {    //a chain of Exception-prone operations    Try.of(Integer::valueOf, "3f")        .map(x -> x * 2)      byte[] mybytes = {0b101, 0b001};            String myString = Try.of(Float::valueOf, "3F")                    .map(f -> f * 2)                    .peek(f -> System.out.println("Float? : " + f))                    .peekFailure(f -> System.out.println("Exception1? : " + f.getThrowable()))                        .map(f -> f / 0)                    .peek(f -> System.out.println("Float? : " + f))                    .peekFailure(f -> System.out.println("Exception2? : " + f.getThrowable()))                        .map(f -> mybytes)                    .peek(b -> System.out.println("bytes? " + b))                    .peekFailure(f -> System.out.println("Exception3? : " + f.getThrowable()))                        .map(bytes -> new String(bytes, 0, 10, "UTF-128"))                    .peek(s -> System.out.println("String? " + s))                    .peekFailure(f -> System.out.println("Exception4? : " + f.getThrowable()))                    .recover(s -> s, f -> f.getMessage());                //Try from a two argument Function    Try<Integer> myTry = Try.of((a, b) -> a / b, 3, 0);    //Try to Option    Optional<Integer> oInt = myTry.toOptional();    //Try to Either    Either<Throwable, Integer> integerEither = myTry.toEither();    //flatMap - a map without nested Try as the result    Integer divByZero = Try.of(Integer::new, 3)            .flatMap(i -> div(i, 0))            .recover(Function.identity(), a -> 0);      //orElse when Failure    Integer shouldEqZero = Try.of((a, b) -> a / b, 1, 0).orElse(0);      //orElseGet when Failure (the fallback Supplier is lazy)    Integer shouldEqZero = Try.of((a, b) -> a / b, 1, 0).orElseGet(() -> 0);      //forEach only runs when success    new Success<>(3)            .forEach(i -> System.out.println("a number : " + i));                //escape the Try structure and enter a regular try-catch flow    Try<Object> myTry = Try.of(() -> {        throw new IOException("floppy drive too busy");    });    try {        myTry.orElseThrow(e -> new AWTException("hah!"));    } catch (AWTException e) {        //handle and/or propagate    }}  private Try<Integer> div(Integer a, Integer b) {    return Try.of((x,y) -> x / y, a, b);}  //this function must end with a valueprivate String handleFailure(Exception e) {    e.printStackTrace();    return "I'm afraid this didnt work because of " + e.getMessage();}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp