{"id":15044578,"url":"https://github.com/jbock-java/either","last_synced_at":"2025-08-21T19:30:56.102Z","repository":{"id":57733621,"uuid":"382392990","full_name":"jbock-java/either","owner":"jbock-java","description":"Functional error handling for Java","archived":false,"fork":false,"pushed_at":"2024-10-24T05:32:03.000Z","size":278,"stargazers_count":41,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-07T14:51:31.306Z","etag":null,"topics":["either","either-monad","error-handling","idiomatic","java-either","java-streams","java11"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jbock-java.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-02T15:47:27.000Z","updated_at":"2024-11-20T08:15:10.000Z","dependencies_parsed_at":"2024-09-28T23:20:32.332Z","dependency_job_id":"d7b04ef6-439a-4b83-8dcf-2655cd146d25","html_url":"https://github.com/jbock-java/either","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jbock-java%2Feither","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jbock-java%2Feither/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jbock-java%2Feither/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jbock-java%2Feither/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jbock-java","download_url":"https://codeload.github.com/jbock-java/either/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230527875,"owners_count":18240052,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["either","either-monad","error-handling","idiomatic","java-either","java-streams","java11"],"created_at":"2024-09-24T20:50:44.951Z","updated_at":"2024-12-20T03:10:33.215Z","avatar_url":"https://github.com/jbock-java.png","language":"Java","readme":"[![either](https://maven-badges.herokuapp.com/maven-central/io.github.jbock-java/either/badge.svg?subject=either)](https://maven-badges.herokuapp.com/maven-central/io.github.jbock-java/either)\n\nThe `Either` type is closely related to `Optional`, but can have different \"failure\" states, other than only *empty*.\n`Either` can be used to collect error messages in stream operations,\nor simply as a lightweight alternative to throwing an Exception.\n\nThere are several popular libraries that offer an `Either` type,\nincluding [vavr](https://github.com/vavr-io/vavr), [fugue](https://bitbucket.org/atlassian/fugue/src/master/), and [lambda](https://github.com/palatable/lambda).\nThis particular `Either` is lightweight, and very easy to work with if you're already familiar with `Optional`.\n\n### empty to Left\n\nSometimes, it can be desirable to put *something* into the \"empty\" value of an `Optional`.\nLet's call this \"adding a *Left* value\", since this value is no longer *empty*.\nGoing from Optional to Either is as easy as mapping with `Either::right`,\nfollowed by an `orElseGet` to supply the Left value:\n\n````java\nEither\u003cString, BigInteger\u003e possiblyPrime = Stream.generate(() -\u003e \n                ThreadLocalRandom.current().nextInt(1000))\n        .map(BigInteger::valueOf)\n        .limit(10)\n        .filter(n -\u003e n.isProbablePrime(10))\n        .findAny()                                      // Optional\u003cBigInteger\u003e\n        .\u003cEither\u003cString, BigInteger\u003e\u003emap(Either::right) // Optional\u003cEither\u003cString, BigInteger\u003e\u003e\n        .orElseGet(() -\u003e Either.left(\"no such value\")); // Either\u003cString, BigInteger\u003e\n````\n\nRepeating the result type in the penultimate line is necessary, due to a limitation of Java's typechecker.\n\n### Working with Either\n\n`Either` has the familiar methods from `Optional`: `map`, `flatMap` and `filter`.\nThese will always return a *Left* value unchanged,\njust like the corresponding methods in `Optional`, which return an *empty* value unchanged.\n\nSymmetrically there are `mapLeft`, `flatMapLeft` and `filterLeft`, which return a *Right* value unchanged.\n\nFinally there is ~~ifPresentOrElse~~ `ifLeftOrElse` (1.3) and the all-powerful `fold` method,\nas well as `getRight` and `getLeft` to convert back to `Optional`.\n\n### Working with streams\n\nIf you have a stream of `Either`, you can search for *Left* values with custom collectors\n`firstFailure` or `allFailures`:\n\n````java\nEither\u003cBigInteger, List\u003cBigInteger\u003e\u003e twoPrimesOrOneComposite = Stream.generate(() -\u003e\n        ThreadLocalRandom.current().nextInt(1000))\n        .map(BigInteger::valueOf)\n        .limit(2)\n        .\u003cEither\u003cBigInteger, BigInteger\u003e\u003emap(n -\u003e n.isProbablePrime(10) ?\n                Either.right(n) : Either.left(n))\n        .collect(Eithers.firstFailure());\n````\n\n### Testimonies\n\nThis library grew for several months as part of the [jbock](https://github.com/jbock-java/jbock) project,\nuntil it was released independently. jbock uses it internally to perform input validation,\nand its generated `parse` method returns an `Either`.\n\n### Either gang\n\n* [spencerwi](https://github.com/spencerwi/Either.java)\n* [ambivalence](https://github.com/poetix/ambivalence)\n* [derive4j](https://github.com/derive4j/derive4j)\n* [mediascience](https://github.com/mediascience/java-either)\n* [pragmatica](https://github.com/siy/pragmatica)\n* [gradle's internal either](https://github.com/gradle/gradle/tree/master/subprojects/functional)\n* [dichotomy](https://github.com/xyzsd/dichotomy)\n\n","funding_links":[],"categories":["\u003ca name=\"Java\"\u003e\u003c/a\u003eJava"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjbock-java%2Feither","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjbock-java%2Feither","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjbock-java%2Feither/lists"}