Functional programming is becoming more and more popular nowadays, and popular imperative languages, like Java, started trying to create functional mechanisms. The main benefits of functional programming are:

Readability — functionalities are written in at high abstract level, which makes logic code easy to understand. This is crucial, especially in cases when, when we need to implement complex business logic, to avoid bugs.

Faster to implement — if you are familiar with functional mechanisms, you are able to write the same code using far fewer lines of code.

Reliability of code — higher-level implementations are more redundant to typical programming mistakes.

In modern programming, advantages of using functional programming, are generally much more important than it’s drawbacks, which results in great popularity of some languages like: Scala, Kotlin or F#. Java, from version 8, also supports functional programming with its streams and Vavr library provides many features, which extends standard Java functional mechanisms. To make use of this post, one should be familiar with the basics of Java’s streams.

Vavr gives us a lot of features, which turn Java into a real functional programming language. Let me show you main features of:

Option

Vavr Option is the same as Java’s Optional, but has some more methods, which makes Option superior to Optional. For example, Option class has method “peek”, which calls passed lambda if there is something in Option, and then returns the same Option. Option is also fully integrated with Vavr’s collections, as we will see further in this post.

Take a look at some typical Option object creations:

Typical use of Option:

Tuple

Tuple is an object, which can hold many objects inside many types. Vavr contains implementations of Tuples being able to hold from 0 up to 8 elements. Each Tuple is named Tuple0, …, Tuple8.

Simple initialization of Tuple2 creates an object which contains the integer: 1 and the String: “dog”.

We can access Tuple’s elements via public fields: _1 or _2. Tuples are very handy to use inside many function calls chains, but be aware to not use too many of them, because they can significantly reduce code readability. For the same reason you also shouldn’t use Tuples in non-private method’s interfaces.

Try

There are many critics of “throw-catch” mechanism. They say, that all error should be processed as a normal function’s results. The main argument against “throw-catch” mechanism is that it breaks program’s flow, which can result in bad code readability. It also may complicate business logic, and is very costly mechanism (processor context switches). Vavr creators found an antidote for this case: Try class. By using Try class, all throws can be processed functionally, which does not break program logic flow.

Let’s imagine, that we want to get results from some function “fun”, which may throw up an exception. To get a result from such a method, we can use Try as follows:

As we have just seen, exceptions are a part of control flow, which is not interrupted by them. Try’s methods, like map, andThen, are executed only if Try has succeeded. Of course, we can run Try for code, which is not returning anything:

There is also a possibility to take advantage of Java’s AutoCloseable interface’s implementations:

Try, after completing its flow, will always invoke close() method on resources passed in the “withResource” method.

In many cases, we can implement methods which use Try object, but we want to return Option, not Try. It makes a lot of sense, for example we can invoke the method which returns Try, but if we ultimately want to return Option, we can do that with “toOption()” method. And there is a trap when mapping Try to Option. Let’s take a closer look at the following code:

When we perform such mapping, we lose information about exceptions, which has been thrown in Try, and we get empty Option instead. It is necessary for locating a potential bug, to log that exception, like:

Collections

All collections available in the Vavr library are immutable ones, which means any operation on those collections like adding new elements or removing elements from collections creates a new collection, which contains those changes, but original collections remainunchanged. One can say that it is a waste of CPU and memory, but in fact, Vavr is designed to share data structures in memory across different versions of the same collection. This is important, because this differentiates Vavr’s collections from Java’s immutable collections from Collections class.

Vavr collections don’t use annoying Java 8 .stream() and them .collect(…) convention. Instead we invoke stream methods directly on collection objects.

List

List implements interface Seq, which is common not only for List, but also: Queue, Array, Stream, Vector. In this post we will focus only on Lists. Lists delivered by Vavr are built like those in Prolog — first element from left side is called head and the rest of the list is another list, called tail. Let’s look at some examples of how to create a new List in Vavr:

Vavr’s List has some handy methods. Let’s take a look at the following examples.

Let’s say you want to generate all permutations of your list, with Vavr, there is nothing simpler:

As I mentioned before, Option is integrated with all Vavr’s objects, including List. Assume that we want to find “dog” in “words” List:

Another example — let’s sum up lengths of Strings inside “words” List:

Sometimes it is necessary to remove List elements until one of them occurrs:

And what in case we want to group our words List by its values length?

Suppose we have two different lists and we want to zip them:

Set

Vavr gives us different implementations of the Set interface: HashSet, TreeSet, LinkedHashSet, BitSet. We will focus on the first two of them. HashSet uses the hashCode Object method to compute values hash and TreeSet is a sorted type of set which is build using Red/Black Tree.

Vavr’s Sets have useful methods to operate on them like on mathematical sets:

Map

There are three implementations of the Map interface in Vavr: HashMap, TreeMap, LinkedHashMap. HashMap hashes its keys values, which makes it very fast but also HashMap can use a lot of memory. TreeMap is, like TreeSet, built on Red/Black Tree which makes it slower than HashMap and LinkedHashMap.

Vavr’s Maps implements some methods which makes them more useful than standard Java’s Maps.

Pattern Matching

The last feature I’m going to show you in this article will be Vavr’s pattern matching. Pattern matching is a mechanism, natively available for example in Scala, whose purpose is to avoid creating if-else chains. This approach reduces a amount of the code and makes the code much cleaner and easy to read.

Let’s take a look at the following example:

Instead of just match return values, there is also a possibility to perform side actions using the “run” method, which takes the “Runnable” as the only parameter. Keep in mind you should always use the “run” method within lambda body, like shown in the example above. In other case, it will be evaluated before pattern matching starts.

We use the “Match” method to create a new matching statement. Then, using “Case” methods we create new cases. “$” is used to define within predicates, which indicate which case will be executed. As seen above, I have used the “is” predicate, which is provided via the Vavr library, but there are also many other predicates. Just look at the following examples:

The Vavr pattern matching mechanism is also convenient to use with the “Option” and “Try” objects:

With the “Option” interface, you are able to use $Some($(predicate)) and $None() predicates as well.

As you might have seen, the same code written using if-else blocks would be difficult to read and less resistant to programming errors, which is why pattern matching mechanisms are popular in functional programming languages, like: Scala, Kotlin or Haskell.

Summary

As you can see, Vavr is a very powerful tool and many say that Vavr is the new Guava. Some people use Vavr only for its collections, but after reading this article one should know that Vavr is much more than only collections. It is a great functional programming tool, which can turn your Java programs into real functional ones.

Go ahead and find more at: http://www.vavr.io/vavr-docs/