1. Overview
Vavr is an open source object-functional language extension library for Java 8+. It helps to reduce the amount of code and to increase the robustness.
In this article, we’ll learn about Vavr‘s tool called Either. If you want to learn more about the Vavr library, check this article.
2. What is Either
In a functional programming world, functional values or objects can’t be modified (i.e. in normal form); in Java terminology, it’s known as immutable variables.
Either represents a value of two possible data types. An Either is either a Left or a Right. By convention, the Left signifies a failure case result and the Right signifies a success.
3. Maven Dependencies
We need to add the following dependency in the pom.xml:
<dependency> <groupId>io.vavr</groupId> <artifactId>vavr</artifactId> <version>0.9.0</version> </dependency>
The latest version of Vavr is available in the Central Maven Repository.
4. Use Cases
Let’s consider a use case where we need to create a method which takes an input and, based on the input, we’ll return either a String or an Integer.
4.1. Plain Java
We can implement this in two ways. Either our method can return a map with the key representing success/failure result, or it could return a fixed size List/Array where position denotes a result type.
This is how this could look like:
public static Map<String, Object> computeWithoutEitherUsingMap(int marks) { Map<String, Object> results = new HashMap<>(); if (marks < 85) { results.put("FAILURE", "Marks not acceptable"); } else { results.put("SUCCESS", marks); } return results; } public static void main(String[] args) { Map<String, Object> results = computeWithoutEitherUsingMap(8); String error = (String) results.get("FAILURE"); int marks = (int) results.get("SUCCESS"); }
For the second approach, we could use the following code:
public static Object[] computeWithoutEitherUsingArray(int marks) { Object[] results = new Object[2]; if (marks < 85) { results[0] = "Marks not acceptable"; } else { results[1] = marks; } return results; }
As we can see, both ways require quite a lot of work, and the final result is not very aesthetically appealing nor safe to use.
4.2. With Either
Now let’s see how we can utilize Vavr‘s Either utility to achieve the same result:
private static Either<String, Integer> computeWithEither(int marks) { if (marks < 85) { return Either.left("Marks not acceptable"); } else { return Either.right(marks); } }
No, explicit type-casting, null checking, or unused object creation is required.
Moreover, Either provides a very handy monadic-like API for dealing with both cases:
computeWithEither(80) .right() .filter(...) .map(...) // ...
By convention, Either’s Left attribute represents a failure case and the Right one represents a success. However, based on our needs we can change this using projections – Either in Vavr is not biased towards Left or Right.
If we project to Right, operations like filter(), map() will have no effect if Either was Left.
For example, let’s create the Right projection and define some operations on it:
computeWithEither(90).right() .filter(...) .map(...) .getOrElse(Collections::emptyList);
If it turns out that we projected Left to the Right, we will get an empty list immediately.
We can interact with the Left projection in a similar way:
computeWithEither(9).left() .map(FetchError::getMsg) .forEach(System.out::println);
4.3. Additional Features
There are plenty of Either utilities available; let’s have a look at some of them.
We can check if an Either contain only Left or Right using isLeft and isRight methods:
result.isLeft(); result.isRight();
We can check if Either contains a given Right value:
result.contains(100)
We can fold Left and Right to one common type:
Either<String, Integer> either = Either.right(42); String result = either.fold(i -> i, Object::toString);
or… even swap sides:
Either<String, Integer> either = Either.right(42); Either<Integer, String> swap = either.swap();
5. Conclusion
In this quick tutorial, we’ve learned about using the Either utility of Vavr‘s framework. More details on Either can be found here.
As always, the full source code is available over on GitHub.