{"id":22662850,"url":"https://github.com/noyzys/avoid-optional","last_synced_at":"2025-08-14T19:07:33.460Z","repository":{"id":266344153,"uuid":"898092866","full_name":"noyzys/avoid-optional","owner":"noyzys","description":"Documentation :: Avoid using java.util.Optional","archived":false,"fork":false,"pushed_at":"2025-05-23T12:59:13.000Z","size":43,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-13T19:03:09.585Z","etag":null,"topics":["avoid","avoiding","docs","guava","java","javautility","kotlin","mistake","optional","vavr"],"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/noyzys.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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,"zenodo":null}},"created_at":"2024-12-03T19:20:57.000Z","updated_at":"2025-05-23T12:59:17.000Z","dependencies_parsed_at":"2025-06-13T19:03:11.069Z","dependency_job_id":"6f2ee350-90e4-4633-8dde-db5a8ba319cd","html_url":"https://github.com/noyzys/avoid-optional","commit_stats":null,"previous_names":["noyzys/avoid-optional"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/noyzys/avoid-optional","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noyzys%2Favoid-optional","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noyzys%2Favoid-optional/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noyzys%2Favoid-optional/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noyzys%2Favoid-optional/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/noyzys","download_url":"https://codeload.github.com/noyzys/avoid-optional/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noyzys%2Favoid-optional/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270467672,"owners_count":24588807,"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","status":"online","status_checked_at":"2025-08-14T02:00:10.309Z","response_time":75,"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":["avoid","avoiding","docs","guava","java","javautility","kotlin","mistake","optional","vavr"],"created_at":"2024-12-09T12:15:57.048Z","updated_at":"2025-08-14T19:07:31.172Z","avatar_url":"https://github.com/noyzys.png","language":"Java","readme":"                                        #  Avoiding `Optional` in Java/Kotlin #\n\n## **Introduction**\nJava package `java.util.Optional` was introduced in Java 8 to address issues related to `null` values. While its intent was to reduce `NullPointerException` and make code safer, its design and implementation have several critical flaws that make it a less ideal solution for \"modern software\" development.\n**Optional in Java 8+ was meant to solve issues related to null, but its implementation in java.util has significant shortcomings. Optional is considered suboptimal in many cases.**\n\nThis document explores the problems with Monad `Optional`, identifies where its use can cause issues, and suggests alternatives.\n**(I won't explain what each concept is, as the focus is mainly on contracts and adhering to SOLID principles. Every Java developer or programmer working with typed, object-oriented programming should understand what this entails.)**\n\n## **Why is Optional a failed idea?**\n\n- It is not a true Monad:\n- Compared to monads in Haskell or Option in Scala, Optional does not fully support a fluent, functional programming style\n- mistake `java.util.Optional` Java standard API.\n\n# Monad \n**A structure in functional programming that represents computations as sequences of steps. A Monad consists/wrapper of:**\n- **A unit constructor (unit or of): Wraps a value into a monad.**\n- **Example: function/method bind or flatMap (fmap): Allows combining operations on values wrapped in a monad.**\n- A monad adheres to the laws of associativity and identity.\n- In Java Optional is a simplified form of a monad, but it does not meet all the requirements (lacking support for the identity function)\n\n### Lack of support in class fields:\n\n- It should not be used as a class field (violates the principles of object encapsulation\n- Not part of the system-wide API:\n- It does not have native integration with Java's API outside the java.util package.\n- Complexity in handling:\n\n\n- **Methods like get(), orElse(), and isPresent() lead to unreadable code and...**\n- `Optional#of,`\n- `Optional#ofNullable,`\n- `Optional#ifPresent`,\n- `Optional#ifPresentOrElse`,\n- `Optional#flatMap`,\n- `Optional#filter`\n- `Optional#orElseThrow`,\n- `Optional#orElseGet`,\n- `Optional#empty`,\n- `Optional#isEmpty`,\n- `Optional#stream`,\n- `Optional#toString`,\n- `Optional#or`\n- `more...`\n- `#AvoidOptional`\n\n### **Debugging Difficulties**:\n   - Errors like `NoSuchElementException` from improper use (`get()` without checking presence) are cryptic.\n   - Stack traces for `Optional` exceptions are harder to trace compared to explicit null checks.\n\n\n- Each `Optional object` adds an extra layer of allocation compared to directly storing the value.\nIn the case of large datasets or frequently created Optional instances, this can lead `to increased memory usage and higher Garbage Collector (GC) costs.`\nIt also changes the semantics of the code.\n- Optional requires to change their approach to handling missing values, which can cause inconsistencies within a team.\nImproper use fields in classes leads to **design anti-patterns.**\n- Complex functional method chains on Optional can be less efficient than simple imperative code.\nMultiple levels of \"wrapping\" values in Optional increase CPU costs.\n- When using Optional as a parameter, the method caller must create an Optional instance before calling the method, which adds unnecessary overhead.\n- Many limitations in usage (e.g., not as a class field, not as a method parameter).\n- Limited support in the Java API, which leads to conversions between Optional and null.\n- Forces unreadable and overly complex constructs.\n- Generates performance issues and runtime errors.\n- more...\n\n\n### Optional in Java 8+ was meant to solve issues related to null (XD):\n- implementation in java.util has significant flaws and mistakes that, in my opinion, should never have occurred.\n\n* **Let’s get into the specifics and real reasons why we should avoid using this monad from java.util, along with descriptions of individual methods. I will describe each method (function), the issue it presents, and how the code should be structured instead.**\n- Optional should not be used as a class field (it violates the principles of object encapsulation).\n- It has no native integration with Java's API outside the java.util package.\n`\n`\n\n`java.util.Optional#method`\n#### 1. Optional#of(T value)\n- **Creates an Optional with the given value. Throws a NullPointerException if the value is null.**\n\n- **The Optional.of() method does not provide protection against null, which was one of the main issues that Optional was designed to solve. If null is passed as the argument, it will throw an exception, which is counterproductive to the goal of avoiding NPE (NullPointerException).**\n\n- Instead of using `Optional.of()`, you should always use `Optional.ofNullable(T value)`, as it can handle null values gracefully without throwing an exception.\n\n\n```java\nOptional\u003cString\u003e opt = Optional.of(null); // throws NullPointerException\n\n// Correct Usage with ofNullable:\nOptional\u003cString\u003e opt = Optional.ofNullable(null); // returns Optional.empty()\n// Using Optional.ofNullable() ensures that null values are safely handled and that no unnecessary exceptions are thrown.\n```\n\n#### 2. Optional#ofNullable(T value)\n- **Creates an Optional with the given value, or Optional.empty() if the value is null.**\n\n- **While `Optional.ofNullable()` is a better alternative to `Optional.of()`, it introduces the possibility of hiding potential issues caused by null. Developers might become overly reliant on this method, using it as a workaround instead of addressing the root cause of the null values. This approach can encourage the continued presence of null values in the system, rather than removing them altogether.**\n\n- **Consider using the Null Object Pattern to completely eliminate null values. `Null Object Patter`n involves creating a default object that represents the absence of a value, instead of relying on null. This helps avoid unnecessary checks for null and provides a clearer, more predictable way to handle missing values.**\n\n\n\n```java\nOptional\u003cString\u003e opt = Optional.ofNullable(null); // returns Optional.empty()\n```\n\n#### 3. Optional#isPresent()\n- **Returns true if the Optional contains a value, otherwise false.**\n\n- **Using isPresent() leads to procedural code that resembles the old approach of checking null with if statements. It forces developers to manually check whether a value is present inside the Optional, which reduces the code's functional style. This defeats the purpose of Optional as a tool for avoiding null checks and introduces unnecessary complexity and verbosity.**\n\n- **Use ifPresent() or other functional methods like map(), flatMap(), or filter(), which align better with a functional programming approach and make the code more concise and readable. These methods handle the presence check implicitly and allow for more declarative code.** \n\n\n\n```java\nOptional\u003cString\u003e opt = Optional.of(\"Avoid\");\nif (opt.isPresent()) {\n    System.out.println(opt.get());  // Procedural code, uses if and get()\n}\n\n// Correct Usage with ifPresent():\nOptional\u003cString\u003e opt = Optional.of(\"Avoid\");\nopt.ifPresent(System.out::println);  // More functional approach, no explicit null checks\n\n//Additional Functional Alternatives:\nOptional\u003cString\u003e opt = Optional.of(\"Avoid\");\nopt.map(String::toUpperCase).ifPresent(System.out::println);  // Transformation and action in one step\n// Using ifPresent() and other functional methods leads to cleaner, more declarative code that reduces manual checks and embraces the functional programming style.\n```\n\n#### 4. Optional#ifPresent(Consumer\u003c? super T\u003e action)\n- **Performs an action if the Optional contains a value. If the Optional is empty, no action is performed.**\n\n- **While ifPresent() is useful for executing an action when a value is present, it can make code harder to read and maintain when the logic inside the action becomes more complex. Additionally, it is limited because it only handles the case when the value is present and does not offer a way to handle the case where the Optional is empty.**\n\n- **Use ifPresentOrElse() (introduced in Java 9), which allows you to handle both the case where the Optional contains a value and the case where it is empty. This provides more flexibility and makes the code more concise by not requiring additional if checks or extra logic.**\n\n\n```java\nOptional\u003cString\u003e opt = Optional.of(\"Avoid\");\nopt.ifPresent(v -\u003e {\n    // complex logic\n    System.out.println(v);  // If logic becomes more complex, readability suffers\n});\n\n// Example with ifPresentOrElse():\nOptional\u003cString\u003e opt = Optional.of(\"Avoid\");\nopt.ifPresentOrElse(\n    v -\u003e System.out.println(v),  // Action if present\n    () -\u003e System.out.println(\"No value present\")  // Action if empty\n);\n// ifPresentOrElse() allows you to handle both the presence and absence of a value in a single, more readable and concise method, reducing the need for multiple if or conditional checks. This improves the clarity of the code, especially in more complex scenarios.\n```\n\n#### 5. Optional#ifPresentOrElse(Consumer\u003c? super T\u003e action, Runnable emptyAction) (Java 9+)\n- **Performs one action if the Optional contains a value, or another action if the Optional is empty. This allows handling both cases (present and empty) in a single method.**\n\n- **While ifPresentOrElse() improves the flexibility of handling both present and absent values, it can lead to unreadable code when the actions (the action and emptyAction) have different levels of complexity. If either of these actions involves complex logic, such as nested lambdas or multiple statements, the code can quickly become hard to read and maintain. Additionally, debugging such code can be challenging due to the increased complexity introduced by lambda expressions.**\n\n\n```java\nOptional\u003cString\u003e opt = Optional.of(\"Avoid\");\n\nopt.ifPresentOrElse(\n    v -\u003e {\n        // Complex logic\n        System.out.println(\"Action: \" + v);\n        // Further processing\n    },\n    () -\u003e {\n        // Complex logic\n        System.out.println(\"Empty: No value found\");\n        // Further processing\n    }\n);\n\n// In cases where the action or the emptyAction involves multiple statements or complex logic, the ifPresentOrElse() method can become cluttered with long lambdas, reducing clarity and making it harder to follow the flow of the program.\n\n// Correct Usage:\n// While ifPresentOrElse() can be useful for simple cases, for more complex logic, consider refactoring the code into separate methods or using map()/flatMap() in combination with orElse() or orElseGet() to handle the actions more cleanly.\n\nOptional\u003cString\u003e opt = Optional.of(\"Avoid\");\n\nopt.ifPresentOrElse(\n    this::handlePresent,  // Refactor complex logic into separate methods\n    this::handleEmpty\n);\n\n// Refactored methods\npublic void handlePresent(String value) {\n    System.out.println(\"Action: \" + value);\n    // ...\n}\n\npublic void handleEmpty() {\n    System.out.println(\"Empty: No value found\");\n    // ...\n}\n```\n- By refactoring complex logic into dedicated methods, you maintain the readability of your code while still taking advantage of ifPresentOrElse() for handling both the present and empty cases. This way, the lambda expressions remain simple, and debugging becomes easier.\n\n\n#### 6. Optional#map(Function\u003c? super T, ? extends U\u003e mapper)\n- **Transforms the value inside the Optional using a provided function. If the Optional is empty, it returns Optional.empty(), otherwise it applies the function to the value and wraps the result in a new Optional.**\n \n- **The use of map() often forces developers to apply additional transformations, especially when dealing with complex types or chaining multiple transformations. This can lead to more complex code that is harder to read and maintain.**\n\n- **map() doesn't handle null values well. If the transformation function can potentially return null, you'll need to apply additional safeguards like Optional.ofNullable() to avoid NullPointerException, which can make the code more convoluted.**\n\n\n```java\nOptional\u003cString\u003e opt = Optional.of(\"Avoid\");\n\nOptional\u003cInteger\u003e length = opt.map(String::length);  // OK - if the function never returns null\n\n// if the transformation function can return null:\n// Could return null if length \u003c 3\n// In the example above, if toUpperCase() or substring() return null, the code can break. Handling this with // Optional.ofNullable() would add complexity.\nOptional\u003cString\u003e transformed = opt.map(s -\u003e s.toUpperCase().substring(0, 3));  \n```\n\n- **Use flatMap() instead of map().**\n\n#### 7. Optional#flatMap(flatMap(Function\u003c? super T, Optional\u003cU\u003e\u003e mapper))\n- **Transforms the value inside the Optional using a provided function, where the function itself returns an Optional\u003cU\u003e. If the Optional is empty, it returns Optional.empty(). This method helps avoid nested Optional\u003cOptional\u003cU\u003e\u003e structures, allowing for cleaner handling of transformations that may return Optional values.**\n\n- **If the functions being passed to flatMap() are complex or involve multiple steps, they can lead to excessive nesting or chaining of logic. This can make the code harder to follow and maintain, as the transformation process becomes more opaque.**\n\n- **When using flatMap() repeatedly in a chain, it can make the code more difficult to read and debug, especially if the transformations involve complex operations or conditional logic. Multiple calls to flatMap() create a series of nested transformations, which can result in a less intuitive flow, especially when mixed with other functional operations.**\n\n\n```java\nOptional\u003cString\u003e opt = Optional.of(\"Avoid\");\n\nOptional\u003cString\u003e result = opt.flatMap(s -\u003e Optional.ofNullable(s.toUpperCase()))\n                             .flatMap(s -\u003e Optional.ofNullable(s.substring(0, 3)))\n                             .flatMap(s -\u003e Optional.ofNullable(s + \"_STYPES\"));\n// In this example, the use of multiple flatMap() calls results in an increasingly complex and deeply nested transformation logic. \n// While each individual flatMap() may seem simple, chaining them together leads to less readable and harder-to-debug code, especially if the transformations become more intricate.\n\n// Issues with Readability and Debugging: The more flatMap() is used in a chain, the harder it becomes to trace the transformations step by step. \n// Each transformation is executed sequentially, but when combined with conditionals, transformations can become difficult to understand at a glance.\n```\n\n#### 8. Optional#orElse(T other)\n- **Returns the value contained in the Optional if present; otherwise, it returns the provided default value other. The default value is evaluated even when the Optional contains a value.**\n\n- **The primary issue with orElse() is that the default value (other) is always evaluated, even if the Optional is not empty. This can result in unnecessary computation or side effects, especially when the default value is a complex expression or an expensive computation.**\n\n- **If the default value involves a costly computation or side effect, using orElse() would waste resources in situations where the Optional is already populated, making it inefficient.**\n\n\n```java\nOptional\u003cString\u003e opt = Optional.of(\"Avoid\");\n\n// The default value (\"default_value\") is evaluated even though the Optional is not empty\nString value = opt.orElse(computeDefaultValue());\n\n// Where computeDefaultValue() could be an expensive operation\nString computeDefaultValue() {\n    // Expensive computation\n    return \"default_value\";\n}\n// In this example, computeDefaultValue() is always executed, even though the Optional contains a value, resulting in unnecessary computation.\n```\n\n- **Use orElseGet(Supplier\u003c? extends T\u003e other), which only evaluates the default value when the Optional is empty. This avoids the unnecessary computation of the default value when it is not required, leading to better performance.**\n\n\n#### 9. Optional#orElseGet(Supplier\u003c? extends T\u003e supplier)\n- **Returns the value contained in the Optional if present; otherwise, it invokes the Supplier to obtain the default value. The Supplier is only evaluated when the Optional is empty.**\n\n- **While orElseGet() is more efficient than orElse(), it requires a Supplier function to be provided, which introduces slightly more complexity in syntax. This may seem cumbersome in cases where a simple default value can be used, especially for developers not familiar with functional programming constructs.**\n\n- **The need to wrap the default value into a Supplier can make the code appear more verbose compared to the simpler orElse() method, particularly when no complex computation is required for the default value.**\n\n\n```java\nOptional\u003cString\u003e opt = Optional.empty();\n\n// Using orElseGet requires wrapping the default value computation in a Supplier\nString value = opt.orElseGet(() -\u003e computeDefault());\n\n// Where computeDefault() could be an expensive operation\nString computeDefault() {\n    // Expensive computation\n    return \"default_value\";\n}\n\n// Here, using orElseGet() requires the lambda expression () -\u003e computeDefault() to wrap the logic that computes the default value, which adds a small but noticeable layer of syntactic complexity.\n```\n\n- **orElseGet() is more efficient than orElse() because it only computes the default value when necessary, but it introduces more syntactic complexity.**\n- **Use orElseGet() when the default value requires computation or a side effect, and use orElse() for simple constants or easy-to-define default values where performance is not an issue.**\n\n\n#### 10. Optional#stream() (Java 9+)\n- **stream() method returns a Stream containing the value inside the Optional if present, or an empty Stream if the Optional is empty. This method allows Optional to be seamlessly integrated into Java's Stream API, enabling you to chain further stream operations.**\n\n```java\nOptional\u003cString\u003e opt = Optional.of(\"Avoid\");\n\n// Converts the Optional into a Stream containing the value\nStream\u003cString\u003e stream = opt.stream();\n\n// The introduction of stream() on Optional (in Java 9) is seen as an attempt to integrate Optional more seamlessly into the Stream API. However, it may appear \"artificial\" or forced. \n// This method doesn't provide much additional value beyond what is already achievable using Optional's other methods like map(), flatMap(), or ifPresent().\n```\n\n#### 11. Optional#empty()\n- **empty() method creates an empty Optional, which is essentially a container that holds no value. This is useful when you want to represent the absence of a value in an Optional.**\n\n```java\nOptional\u003cString\u003e emptyOpt = Optional.empty();\n\n// One of the main criticisms of Optional.empty() is that it can be overused as a default value, which can lead to a pattern that is similar to using null. While Optional is meant to represent the presence or absence of a value, relying on Optional.empty() too frequently may defeat the purpose of providing a more explicit way of handling null. In some cases, Optional.empty() can make the code harder to understand because it introduces another abstraction layer without adding much clarity.\n```\n\n- **While Optional is meant to be a safer alternative to null, using Optional.empty() too often risks reintroducing the same confusion around the meaning of \"no value\". A value of Optional.empty() can be interpreted in different ways, depending on context, which can lead to misunderstandings or errors when different developers interpret the absence of a value.**\n\n- **Sometimes, using empty collections or other idiomatic representations of \"no value\" (such as an empty list or map) can be more semantically clear than using Optional.empty(). For example, returning an empty List or Map directly from a method may better convey that no elements are present, while still allowing the consumer of the method to process it as a collection.**\n\n- **While it converts Optional into a Stream, it doesn't offer the same full-fledged support as regular collections (like Lists or Sets). You can treat an Optional as a stream, but you can't directly perform collection-like operations (iltering multiple values or sorting).**\n\n\n#### 12. Optional#isEmpty() (Java 11+)\n-- **sEmpty() method returns true if the Optional is empty (contains no value). It is the opposite of the isPresent() method, which checks if the Optional contains a value.**\n\n```java\nOptional\u003cString\u003e opt = Optional.empty();\nboolean isEmpty = opt.isEmpty();  // Returns true\n```\n\n- **isEmpty() creates redundancy with the already existing isPresent() method, which serves as a way to check if the Optional contains a value. Both methods do essentially the same thing but with opposite semantics. This can lead to confusion and inconsistency in code, as developers now have to choose between isPresent() and isEmpty(), which do the same thing in a negated manner.**\n\n\n#### 13. Optional#get() \n- **get() method in the Optional class returns the value contained within the Optional if it is present. If the Optional is empty (i.e., does not contain a value), it throws a NoSuchElementException.**\n\n```java\nOptional\u003cString\u003e optional = Optional.of(\"Avoid\");\nString value = optional.get();  // Returns \"Avoid\"\n\nOptional\u003cString\u003e emptyOptional = Optional.empty();\nString emptyValue = emptyOptional.get();  // Throws NoSuchElementException\n```\n\n- **One of the key principles of monads, including Optional, is to safely handle the absence of values without requiring explicit checks. The get() method violates this principle because it forces the programmer to manually handle the empty case by throwing an exception, rather than offering a more functional way of managing the absence of a value (e.g., using methods like map(), ifPresent(), or orElse()).**\n\n- **A Monad should offer a way to deal with \"no value\" without throwing exceptions, which breaks the principle that developers should not manually check for the absence of values.**\n\n- **Requires isPresent() Check Before Calling get():\nUsing get() in combination with isPresent() before calling it reintroduces an old, unsafe approach reminiscent of checking null. This is not in line with the modern, functional programming style.**\n\n```java\nOptional\u003cString\u003e opt = Optional.ofNullable(null);\n\n// Bad practice: we have to check if there is a value before calling get()\nif (opt.isPresent()) {\n    String value = opt.get();  // Can throw NoSuchElementException if Optional is empty\n}\n\n// The get() method does not provide any alternative when the Optional is empty, which forces programmers to deal with exceptions (e.g., NoSuchElementException). This makes the method unsafe to use compared to methods that provide a default value, like orElse() or orElseGet().\n\n// BAD PRACTICE DONT NOT USE get\nString value = opt.get();  // NoSuchElementException\n```\n\n#### 14. Optional#filter(Predicate\u003c? super T\u003e predicate) \n**And many, many more issues and problems with the methods in the facade API of java.util.Optional that I have listed—those which cause mess and clutter in your code.**\n\n####  Optional#isPresent() + get() – Anti-pattern\n**- Using the combination of isPresent() and get() introduces redundancy and manual management of the presence of a value**\n\n```java\nif (opt.isPresent()) {\n    String value = optionalValue.get();\n    System.out.println(value);\n}\n```\n\n#### And..\n- **Using Optional as a Method Parameter**\n- **Using Optional as a Class Field**\n-  It should not be used as a class field (violates the principles of object encapsulation)\n- **Calling get() without Checking Presence**\n- **Creating Optional from null**\n-  **Nested Optional (Anti-pattern)**\n\n## Further Analysis of the Optional Class Methods and Monad\n- **Usage of Optional largely depends on context. However, in this analysis, I aim to demonstrate why it is better to avoid using Optional altogether.**\n\n**This repository explores the problems with `Optional`, identifies where its use can cause issues, and suggests alternatives.**\n\n- **1. Use libraries like [vavr](https://github.com/vavr-io/vavr) for Option, which is a more feature-complete monadic type**\n- **Javaslang**\n- **Vavr (formerly Javaslang) is a Popular Functional Library in Java**\n- **It implements Option in a way that is closer to true monads.**\n- **Fully Functional API**\n- **Exceptionally readable and efficient**\n- **2. [guava](https://github.com/google/guava) Optional wrapper**\n- **3. Null Object Pattern**\n- **4. Create default, no-op implementations to handle missing values.**\n- **5. Use @Nullable and @NonNull annotations to ensure null-safety during compilation [jetbrains](https://github.com/JetBrains/JetBrains.Annotations)**\n- **5. Result/Either Constructs property**\n- **Either Allows Handling Two Possible States (Value and Error)**\n\n## Summary\n**Optional from java.util is a limited implementation of the Option concept.**\n**This is Not an Argument to Immediately Use Vavr\nRather, it highlights the conflicts and errors you may encounter when using java.util.Optional. The main focus is on performance and convenience.**\n**This Illustrates the Practical Use of This Monad\nChoose what you think is better; however, personally, I hate it...**\n**This Represents the Minority That Reveals the True Nature of the Optional Concept in java.util.**\n\n**Finally, Here's a Dose of Bad Practices with Optional That You Should Avoid If You Plan to Use It.**\n[Optional::BadPractices](https://github.com/noyzys/avoid-optional/blob/main/OptionalBadPractices.java)\n\n**I Base This on My Skills, Knowledge, and Experience in English.\nIf I’ve made any linguistic mistakes — my apologies. Additionally, I’d like to note that I’m not a programmer by profession.**\n\n\n**If you are interested in exploring functional programming and its applications within this project visit the repository at [vavr-in-action](https://github.com/noyzys/bukkit-vavr-in-action), [fp-practice](https://github.com/noyzys/fp-practice).**\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoyzys%2Favoid-optional","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnoyzys%2Favoid-optional","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoyzys%2Favoid-optional/lists"}