{"id":37021778,"url":"https://github.com/arcanemage/javalaboratories-java-extensions","last_synced_at":"2026-01-14T02:35:22.294Z","repository":{"id":48407330,"uuid":"249965886","full_name":"ArcaneMage/javalaboratories-java-extensions","owner":"ArcaneMage","description":"This is a library of utilities to encourage functional programming in Java, particularly for Java-8 developers but not exclusively.","archived":false,"fork":false,"pushed_at":"2025-07-12T01:12:37.000Z","size":1877,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-08-16T23:47:41.109Z","etag":null,"topics":["functional-programming","functor","java-extensions","lambda-expressions","monad","thread"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ArcaneMage.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-03-25T11:56:14.000Z","updated_at":"2024-04-25T07:06:41.000Z","dependencies_parsed_at":"2024-09-08T09:33:43.545Z","dependency_job_id":"cf22afdc-9581-4d65-bd64-8de2e910bbcf","html_url":"https://github.com/ArcaneMage/javalaboratories-java-extensions","commit_stats":null,"previous_names":["arcanemage/excelsior-software-java-extensions"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/ArcaneMage/javalaboratories-java-extensions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArcaneMage%2Fjavalaboratories-java-extensions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArcaneMage%2Fjavalaboratories-java-extensions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArcaneMage%2Fjavalaboratories-java-extensions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArcaneMage%2Fjavalaboratories-java-extensions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ArcaneMage","download_url":"https://codeload.github.com/ArcaneMage/javalaboratories-java-extensions/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArcaneMage%2Fjavalaboratories-java-extensions/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408711,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["functional-programming","functor","java-extensions","lambda-expressions","monad","thread"],"created_at":"2026-01-14T02:35:21.597Z","updated_at":"2026-01-14T02:35:22.279Z","avatar_url":"https://github.com/ArcaneMage.png","language":"Java","readme":"# java-extensions\n\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.javalaboratories/java-extensions/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.javalaboratories/java-extensions)\n\nThis is a library of utilities to encourage and support functional programming in Java, With inspiration from functional \nprogramming articles and languages like Haskell and Scala, new monads and enhancements to existing ones have been introduced.\nThis page provides a brief description of the objects in the library, but it is encouraged to review the javadoc \ndocumentation for additional information and examples. \n\n### Maven Central Repository\nThe library is now available for download from Maven Central Repository. In the POM file add the maven dependency \nconfiguration below:\n```\n        \u003c!-- https://mvnrepository.com/artifact/org.javalaboratories/java-extensions --\u003e\n        \u003cdependency\u003e\n          \u003cgroupId\u003eorg.javalaboratories\u003c/groupId\u003e\n          \u003cartifactId\u003ejava-extensions\u003c/artifactId\u003e\n          \u003cversion\u003e2.0.1.0-RELEASE\u003c/version\u003e\n        \u003c/dependency\u003e\n```\nAlternatively, for `Gradle` users, amend the `build.gradle` file with the following:\n```\n        // https://mvnrepository.com/artifact/org.javalaboratories/java-extensions\n        compile group: 'org.javalaboratories', name: 'java-extensions', version: '2.0.1.0-RELEASE'\n```\n### CryptographyFactory\nUse the `CryptographyFactory` class to gain access to both symmetric and asymmetric cryptography objects. It provides\na simple abstraction over the `Java Cryptography Archetecture (JCA)`. It provides not just decryption and encryption\nfunctionality but also includes signing and verification. In the case of RSA encryption that is not capable of \nencrypting large data, a hybrid approach is introduced to enable RSA encryption/decryption of large amounts of data. \nExplore the package but here's an example of usage of the library:\n```\n       // Symmetric cryptography\n       AesCryptography cryptography = CryptographyFactory.getSymmetricCryptography();\n       ByteCryptographyResult\u003cSymmetricKey\u003e result = cryptography.encrypt(SymmetricKey.from(PASSWORD), TEXT);\n       String encrypted = result.getBytesAsBase64();\n\n       ByteCryptographyResult\u003cSymmetricKey\u003e stringResult = cryptography.decrypt(SymmetricKey.from(PASSWORD),encrypted);\n       assertEquals(TEXT, stringResult.getString().orElseThrow());\n       \n       // Asymmetric cryptography\n       RsaHybridCryptography cryptography = CryptographyFactory.getAsymmetricHybridCryptography();\n       ByteCryptographyResult\u003cPublicKey\u003e result = cryptography.encrypt(publicKey,TEXT);\n\n       ByteCryptographyResult\u003cPrivateKey\u003e stringResult = cryptography.decrypt(privateKey, result.getBytesAsBase64());\n\n       assertNotNull(result.getKey());\n       assertEquals(TEXT, stringResult.getString().orElseThrow());\n       \n       // Signing / Verfication\n       RsaMessageSigner signer = CryptographyFactory.getMessageSigner(prvateKey);\n       Message message = signer.encrypt(publicKey,TEXT);\n       \n       // Note that verification does not require a public key, this is \"transmitted\" in the ciphertext\n       // and decoded at the recipient's end and then used to verify the message.\n       RsaMessageVerifier verifier = CryptographyFactory.getMessageVerifier();\n       String s = verifier.decryptAsString(privateKey,message.getSignedAsBase64());\n\n       assertEquals(TEXT, s);\n```\nThe `PublicKey` and `PrivateKey` require the use of the `KeyFactory` or `openssl`. Review the factory and other related\nclasses for more information in the cryptography package.\n### Either\n`Either` class is a container, similar to the `Maybe` and `Optional` classes, that represents one of two possible values\n(a disjoint union). Application and/or sub-routines often have one of two possible outcomes, a successful completion or\na failure, and so it is common to encapsulate these outcomes within an `Either` class. Convention dictates there is a \n`Left` and `Right` sides; \"left\" considered to be the \"unhappy\" outcome, and the \"right\" as the \"happy\" outcome or path.\nSo rather than a method throwing an exception, it can return an `Either` implementation that could be either a `Left` \nor a `Right` object, and thus allowing the client to perform various operations and decide on the best course of action.\nIn the example, the `parser.readFromFile` method returns an `Either` object, but notice the concise `client` code and \nreadability and how it neatly manages both \"unhappy\" and \"happy\" outcomes.\n```\n        // Client code using parser object.\n        String string = parser.readFromFile(file)\n                .flatMap(parser::parse)\n                .map(jsonObject::marshal)\n                .fold(Exception::getMessage,s -\u003e s);\n        ...\n        ...\n        // Parser class (partial implementation)\n        public class Parser {\n            public Either\u003cException,String\u003e readFromFile(File file) {\n            try {\n                ...\n                return Either.right(fileContent)\n            } catch (FileNotFoundException e) {\n                return Either.left(e);\n            }\n        }\n```\nProvided implementations of the `Either` are right-biased, which means operations like `map`,`flatMap` and others have \nno effect on the `Left` implementation, such operations return the \"left\" value unchanged.\n### Eval\nSome objects are expensive to create due to perhaps database access and/or complex calculations. Rather than creating\nthese objects before they are actually needed, `Eval` can leverage a lazy strategy, offering the access to the underlying\n `value` only at the point of use. Essentially, the library introduces three main strategies:\n 1. _Always_ - Evaluation always retrieves the `value` at the point of use -- no caching is involved.\n 2. _Eager_  - Evaluation occurs immediately and the `value` is therefore readily available.\n 3. _Later_  - Evaluation retrieves the `value` at the point of use and caches it for efficient retrieval.\n Like `Maybe`, `Either` and other objects provided in this library, `Eval` implements `flatMap`, `map` and other useful\n operations. Scala's Cat library and lazy design pattern provided the inspiration for this object.\n```\n        Eval\u003cInteger\u003e eval = Eval.later(() -\u003e {\n            logger.info (\"Running expensive calculation...\",value);\n            return 1 + 2 + 3;\n        })\n        // eval = Later[unset]\n\n        eval.get();\n        // Running expensive calculation...\n        // eval = Later[7]\n\n        eval.get();\n        // eval = Later[7]\n```\nIn the above case, `eval` object caches the results of the calculation, hence no repetition of the \"Running expensive \ncalculation\" message. Review javadoc for additional details on supported operations. \n### EventBroadcaster\n`EventBroadcaster` class has the ability to notify its `subscribera` of events they are interested in. It is a partial\nimplementation of the `Observer Design Pattern`. To complete the design pattern, implement the `EventSubscriber` \ninterface and subclass `AbstractEvent` class for defining custom events or use the out-of-the-box `Event` objects in the\n `CommonEvents` class. It is recommended to encapsulate the `EventBroadcaster` object within a class considered to be \n observable. \n```\n        public class DownloadEvent extends AbstractEvent {\n            public static final DOWNLOAD_EVENT = new DownloadEvent();\n            public DownloadEvent() { super(); }\n        }\n\n        public class News implements EventSource {\n            private EventPublisher\u003cString\u003e publisher;\n            \n            public News() {\n                publisher = new EventBroadcaster\u003c\u003e(this);\n            }\n\n            public void addListener(EventSubscriber subscriber, Event... captureEvents) {\n                publisher.subscribe(subscriber,captureEvents);\n            }\n\n            public void download() {\n                ...\n                ...\n                publisher.publish(DOWNLOAD_EVENT,\"Complete\");\n                ...             \n            }\n        }\n        ...\n        ...\n        public class NewsListener implements EventSubscriber\u003cString\u003e {\n            public notify(Event event, String value) {\n                logger.info (\"Received download event: {}\",value);\n            }\n        }\n        ...\n        ...\n        public class NewsPublisherExample {\n            public static void main(String args[]) {\n                News news = new News();\n                NewsListener listener1 = new NewsListener();\n                NewsListener\u003cString\u003e listener2 = (event,state) -\u003e logger.info(\"Received download event: {}\",state);\n\n                news.addListener(listener1,DOWNLOAD_EVENT);\n                news.addListener(listener2,DOWNLOAD_EVENT);\n\n                news.download();\n            }\n        }\n```\nThe `EventBroadcaster` class is thread-safe, but for additional information on this and associated classes, please refer\n to the javadoc details.\n\n### Floadgate, Torrent\nThese classes are used to detect possible thread-safe issues in target objects by subjecting them to method calls \nfrom multiple threads. Currently, they do no assert the state of the target object, but generate log information\nfor analysis. Each `Floodgate` is configured with a specific number of thread workers with each worker calling the \ntarget object's method repeatedly for a configured number of times. For example the `Floodgate` in the example code below\nconfigures 5 (default) thread workers to repeatedly call the `add(10)` method 5 (default) times, and so the expected \ntotal of the additions is 250, as opposed to 240, clearly indicating lost updates. \n```\n        Floodgate\u003cInteger\u003e floodgate = new Floodgate\u003c\u003e(UnsafeStatistics.class, () -\u003e statistics.add(10));\n\n        floodgate.open();\n        List\u003cInteger\u003e results = floodgate.flood();\n\n        logger.info(\"UnsafeStatics statistics={}\", unsafe);\n\n        \u003e\u003e output:  statistics=UnsafeStatistics(total=240, requests=24, average=10.0 \n```\n`Floodgate` is really designed to flood one method/resource, but it is possible to target multiple methods of an object \nunder test with this class, but consider the use of `Torrent` instead for this purpose. `Torrent` manages and controls \nmultiple `Floodgates`, ensuring a fairer distribution of thread workers in the core thread pool as well as triggering the \nflood of all floodgates simultaneously. These features increase the likelihood of detecting thread-safe issues in the \ntarget object. Review the javadoc for more information.\n```\n        Torrent torrent = Torrent.builder(UnsafeStatistics.class)\n                .withFloodgate(\"print\", () -\u003e unsafe.print()) \n                .withFloodgate(\"add\", () -\u003e unsafe.add(10))\n                .build();\n\n        torrent.open();\n        torrent.flood();\n``` \n### Handlers\nHandlers class provides a broad set of wrapper methods to handle checked exceptions within lambda expressions. Lambdas \nare generally short and concise, but checked exceptions can sometimes cause the lambda expression to look unwieldy. \nThis class has many useful methods that compliment common functional interfaces. Each method wraps the function object \ninto a function that transforms the checked exception to a `RuntimeException` object.\n\nFor example, here is an example of a method performing file input/output:\n```\n        public void writeFile(String file) throws IOException {\n            ...\n        }\n \n        // Common technique is to handle the checked exception within the lambda expression :-\n        \n        Consumer\u003cString\u003e consumer = s -\u003e {\n            try {\n                writeFile(s)\n            } catch (IOException e) {\n                ...\n            }\n        }\n \n        // But using the Handlers class, the expression becomes :-\n \n        Consumer\u003cString\u003e consumer = Handlers.consumer(s -\u003e writeFile(s));\n```\n### Holders\nIn cases where it may be necessary to capture and manipulate values from or in lambdas, often containers are used, such as\nAtomic wrappers. This library now has new and improved Holders that are themselves applicatives, monads and functors, which\nmeans `map`, `flatMap` and others are available for operations on the contained value. The most basic operations include\nthe `get` and `set` methods to read or mutate the contained value. Although they are mutable, holder objects are thread-safe, \nin that the reference to the contained value cannot be changed by more than one thread. Ensure the contained value is \nitself thread-safe to guarantee complete thread safety. Factory methods are provided to create both mutable immutable\nholders. Below, are examples of usage:\n```\n        // This example demenstrates side-effects where the Holder object\n        // captures the subtotal of the even numbers. Although it is mutated\n        // it is thread-safe.\n        Holder\u003cDouble\u003e total = Holder.of(0.0);\n        IntStream\n                .range(0,1000)\n                .parallel()\n                .filter(n -\u003e n % 2 == 0)\n                .forEach(n -\u003e total.setGet(v -\u003e v + n));;\n\n        assertEquals(249500.0, total.get());\n\n        ...\n        ...\n                \n        // In this example, the Holder object is created and mutated within the \n        // context of the reducer.\n        List\u003cInteger\u003e numbers = Arrays.asList(5,6,7,8,9,10,1,2,3,4);\n        String result = numbers.parallelStream()\n                .filter(n -\u003e n % 2 == 0)\n                .reduce(Holder.of(0.0),(h,v) -\u003e h.map(n -\u003e n + v),(a,b) -\u003e a.map(n -\u003e n + b.fold(0.0,v -\u003e v)))\n                .map(n -\u003e n / 2)\n                .fold(\"\",n -\u003e STR.\"Sum of even numbers (2,4,6,8,10) / 2 = \\{n}\");\n\n        assertEquals(\"Mean of even numbers (2,4,6,8,10) / 2 = 15.0\",result);\n```\nIn addition to the above, Holder objects come supplied with helper classes to perform operations such as `sum`, `max` and \n`min` within streams. Explore the `Holders` package for more information:\n```\n        List\u003cInteger\u003e numbers = Arrays.asList(5,6,7,8,9,10,1,2,3,4);\n        String result = numbers.parallelStream()\n               .filter(n -\u003e n % 2 == 0)\n               .map(Double::valueOf)\n               .collect(DoubleHolders.summing())\n               .map(n -\u003e n / 2)\n               .fold(\"\",n -\u003e STR.\"Sum of even numbers (2,4,6,8,10) / 2 = \\{n}\");\n\n        assertEquals(\"Sum of even numbers (2,4,6,8,10) / 2 = 15.0\",result);\n        logger.info(result);\n```\n### Maybe\nThe library introduces `Maybe` class, which is a \"drop-in\" replacement for `Optional`. It has features that are only \navailable in the `Optional` class in Java-9/11/13 but it also includes new features. For example, the following is\n possible:\n```\n    Maybe\u003cPerson\u003e person = people.findById(10983);\n    \n    person.forEach(System.out::println);    \n    \n    ...\n    \n    person.ifPresentOrElse(System.out::println, () -\u003e System.out.println(\"Person not found\"))\n    \n    ...\n    \n    List\u003cPerson\u003e list = person.toList();\n```\nSimilarly, there are `NullableInt`,`NullableLong` and `NullableDouble` for `int`,`long` and `double` types respectively. \nRelease v1.0.5 includes many new features found in Scala and Haskell such as `filterNot`, `flatten` and `fold`-- \nreview javadoc for further details.\n### Promise\nThe `Promise` object is a lightweight abstraction of the `CompletableFuture` object, the inspiration of which came from \nthe JavaScript's Promise object behaviour. This implementation provides an easily understood API for asynchronous \nsubmission of tasks encapsulated as `Action` objects with comprehensive exception management. The example below \ndemonstrates the ability to perform I/O and transformation of data asynchronously, which is then output to the console \nin the main thread:\n```\n    Promise\u003cString\u003e promise = Promises\n       .newPromise(PrimaryAction.of(() -\u003e doLongRunningTask(\"Reading integer value from database\")))\n       .then(TransmuteAction.of(value -\u003e \"Value read from the database: \"+value));\n \n       String result = promise.getResult()\n            .IfPresent(result -\u003e System.out::println(result)); \n``` \nThere's a lot more to discover about `Promise` objects -- review the source's Javadoc for details. \n### Reducers\n`Reducers` are collectors but with a difference. Most of them return `Stream` objects, and so it is possible to continue\nfunctional programming within a stream context. Many of the `Collectors` methods have been implemented in `Reducers` class, \nagain as a possible \"drop-in\" replacement for `Collectors` class. `Reducers` also support a comprehensive set of statistical\ncalculations such as mean, median, mode, standard deviation and much more. Expect to see an expansion of statistical \nfunctions in this area over the coming days.\n```\n        List\u003cString\u003e strings = Arrays.asList(\"9\",\"7\",\"5\",\"76\",\"2\",\"40\",\"101\");\n\n        strings.stream()\n                .map(Integer::parseInt)\n                .peek(n -\u003e System.out.print(n+\" \"))\n                .collect(Reducers.summingInt(Integer::valueOf))\n                .findFirst()\n                .ifPresent(n -\u003e System.out.println(\"= \"+n)); \n\n                \n        Outputs: 9 7 5 76 2 40 101 = 240         \n```\n### StopWatch\nStopWatch provides a convenient means for timings of methods. There are no explicit methods in the class to start and \nstop the timings, because these are naturally determined through the process of invoking the function that is currently\nbeing timed. In other words, executing the function will start the `StopWatch` and when the function comes to a \nnatural/unnatural conclusion, the `StopWatch` is automatically stopped. Number of instances of `StopWatch` is unlimited,\nand so useful statistics are available of all the timed functions via the class' methods or via the `StopWatch.getTime` \nmethods. Every `StopWatch` instance has a unique name, which is useful when reviewing the timings. Use the\n`StopWatch.time(Runnable)` method to start the timings.\n```\n         StopWatch stopWatch = StopWatch.watch(\"methodOne\");\n         StopWatch stopWatch2 = StopWatch.watch(\"methodTwo\");\n \n         // This is a common usecase of the StopWatch\n         stopWatch.time(() -\u003e doSomethingMethod(1000));\n \n         // Want review all the timings? This is easy!\n         StopWatch.forEach((a,b) -\u003e logger.info(\"{} \\t-\u003e {}\",a,b));\n         \n         // Output :-\n         10:47:20.394 [main] INFO  StopWatch - methodOne \t-\u003e 00:00:01.000\n         10:47:20.399 [main] INFO  StopWatch - methodTwo \t-\u003e 00:00:00.000\n```\n### Tuples\nA tuple can be considered as a container of ordered elements of different types. Each element may not relate to each\nother but collectively they have meaning. They are particularly useful for methods in that they enable them to \nreturn multiple values as a single tuple object, as well as passing several values to a method in a single argument(s).\nThe tuple has many abilities including `join`, `truncateAt`, `mapAt`, `match`,`toList`,`toMap` and much more. Another \nparticularly useful feature of tuples is that they are immutable, making them thread-safe. Moreover, they all implement \nthe `Iterable`, `Serializable`, and `Comparable` interfaces, allowing their contents can be traversed easily, sortable in \ncollections and persistable. Here are some examples of usage:\n```\n        Tuple3\u003cString,Integer,Integer\u003e tupleEarth = of(\"Earth\",7926,92955807);\n        // tupleEarth: (\"Earth\",7926,92955807), diameter in miles, distance from Sun in miles\n\n        tupleEarth.value2();\n        // tupleEarth.value2(): 7926\n\n        Tuple3\u003cString,Integer,Integer\u003e kmEarth = tupleEarth.mapAt2(t -\u003e Math.round((t / (float) 0.621371)));\n        // tupleEarth: (\"Earth\",12756,92955807), diameter in km\n\n        Tuple5\u003cString,Integer,Integer,String,Integer\u003e tupleEarthMoon = tupleEarth.join(of(\"Moon\",2159));\n        // earthMoon: (\"Earth\",7926,92955807,\"Moon\",2159), joined moon, diameter of 2159\n\n        Tuple2\u003cTuple3\u003cString,Integer,Integer\u003e,Tuple2\u003cString,Integer\u003e\u003e tuplePlanetaryBodies = tupleEarthMoon.spliceAt4();\n        // planetaryBodies: ((\"Earth\",7926,92955807),(\"Moon\",2159))\n\n        tupleEarth = tuplePlanetaryBodies.value1();\n        // tupleEarth: (\"Earth\",7926,92955807)\n\n        Tuple3\u003cString,Integer,Integer\u003e tupleMoon = tuplePlanetaryBodies.value2().join(92900000);\n        // tupleMoon: (\"Moon\",2159,92900000), added moon distance from Sun\n\n        Tuple7\u003cString,String,String,String,String,String,String\u003e tupleCoordinates = tupleEarth\n                .truncateAt2()\n                .addAt1(\"Milky Way\")\n                .join(of(\"Europe\",\"England\",\"Blackfriars\",\"London\",\"EC2 1QW\"));\n        // tupleCoordinates: (\"Milky Way\",\"Earth\",\"Europe\",\"England\",\"Blackfriars\",\"London\",\"EC2 1QW\")\n\n        List\u003c?\u003e list = tupleCoordinates.toList();\n        // list: [\"Milky Way\",\"Earth\",\"Europe\",\"England\",\"Blackfriars\",\"London\",\"EC2 1QW\"]\n\n        tupleEarth.match(allOf(\"^Earth$\"),(a,b,c) -\u003e logger.info(\"Earth's distance from Sun {}\",c));\n        // Outputs: \"Earth's distance from Sun 92955807\"\n```\n### Try\n`Try` is another class that represents a computation/operation that may either result in an exception or a success.\nIt is similar to the `Either` class type, but it dynamically decides the success/failure state. The implementation of the\n`Try` class is inspired by Scala's Try class, and is considered to be a monad as well as a functor, which means the \ncontext of the container is transformable via the `flatMap` and `map` methods.\n\nBelow are some use cases demonstrating the elegant recovery strategies and other features:\n````\n        // Recovering from arithmetic exceptions: result1=\"Result1=1000\"\n        String result1 = Try.of(() -\u003e 100 / 0)\n                            .recover(t -\u003e t instanceof ArithmeticException ? 100 : 100)\n                            .map(n -\u003e n * 10)\n                            .filter(n -\u003e n \u003e 500)\n                            .fold(\"\",n -\u003e \"Result1=\"+n);\n\n        // Using orElse to recover: result2=\"Result2=2500\"\n        String result2 = Try.of(() -\u003e 100 / 0)\n                            .orElse(100)\n                            .map(n -\u003e n * 25)\n                            .filter(n -\u003e n \u003e 500)\n                            .fold(\"\",n -\u003e \"Result2=\"+n);\n\n        // IOExceptions are handled gracefully too: result3=0\n        int result3 = Try.of(() -\u003e new String(Files.readAllBytes(Paths.get(\"does-not-exist.txt\"))))\n                            .orElse(\"\")\n                            .map(String::length)\n                            .fold(-1,Function.identity());\n````\nThere are many more operations available, the API is documented, so go ahead and explore them. There is a potential case\nto abandon the use of the try-catch block in favour of a more functional programming approach.\n\n## Feedback\nDevelopment is ongoing. I have many ideas in the pipeline, and of course will consider your ideas and recommendations. \nIf you encounter any bugs, please raise an issue(s).\n\n## License\nLicensed under the Apache License, Version 2.0 (the \"License\")\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farcanemage%2Fjavalaboratories-java-extensions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farcanemage%2Fjavalaboratories-java-extensions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farcanemage%2Fjavalaboratories-java-extensions/lists"}