1. Overview
As Vavr primarily works within the Java ecosystem, there’s always a need to convert Vavr’s data structures into Java-understandable data structures.
For example, consider a function which returns an io.vavr.collection.List, and we need to pass on the result to another function which accepts java.util.List. This is where the Java-Vavr interoperability comes in handy.
In this tutorial, we’re going to look at how to convert several Vavr data structures into our standard Java collections and vice versa.
2. Vavr to Java Conversion
The Value interface in Vavr is a base interface for most Vavr tools. Thus, all Vavr’s collections inherit the properties of Value.
This is useful as the Value interface comes with a lot of toJavaXXX() methods that allow us to convert the Vavr data structures to Java equivalents.
Let’s see how a Java List can be obtained from the List or Stream of Vavr:
List<String> vavrStringList = List.of("JAVA", "Javascript", "Scala");
java.util.List<String> javaStringList = vavrStringList.toJavaList();
Stream<String> vavrStream = Stream.of("JAVA", "Javascript", "Scala");
java.util.List<String> javaStringList = vavrStream.toJavaList();
The first example converts a Vavr list to a Java list, and the next one converts a stream to Java list. Both examples rely on the toJavaList() method.
Similarly, we can obtain other Java collections from Vavr objects.
Let’s see another example of converting a Vavr Map to a Java Map:
Map<String, String> vavrMap = HashMap.of("1", "a", "2", "b", "3", "c");
java.util.Map<String, String> javaMap = vavrMap.toJavaMap();
Besides standard Java collections, Vavr also provides APIs for converting values to Java streams and Optionals.
Let’s see an example of obtaining an Optional using the toJavaOptional() method:
List<String> vavrList = List.of("Java");
Optional<String> optional = vavrList.toJavaOptional();
assertEquals("Java", optional.get());
As an overview of the Vavr methods of this type, we have:
- toJavaArray()
- toJavaCollection()
- toJavaList()
- toJavaMap()
- toJavaSet()
- toJavaOptional()
- toJavaParallelStream()
- toJavaStream()
A full list of useful APIs can be found here.
3. Java to Vavr Conversion
All the collection implementations in Vavr have a base type of Traversable. Thus, each collection type features a static method ofAll() that takes an Iterable and converts it to the corresponding Vavr collection.
Let’s see how we can convert a java.util.List to a Vavr List:
java.util.List<String> javaList = Arrays.asList("Java", "Haskell", "Scala");
List<String> vavrList = List.ofAll(javaList);
Similarly, we can use the ofAll() method to convert Java streams to Vavr collections:
java.util.stream.Stream<String> javaStream
= Arrays.asList("Java", "Haskell", "Scala").stream();
Stream<String> vavrStream = Stream.ofAll(javaStream);
4. Java Collection Views
The Vavr library also provides Java collection views which delegate calls to the underlying Vavr collections.
The Vavr to Java conversion methods creates a new instance by iterating through all elements to build a Java collection. This means the performance of the conversion is linear, whereas the performance of creating collection views is constant.
As of writing this article, only the List view is supported in Vavr.
For the List, there are two methods that are available to get our View. First is asJava() which returns an immutable List and the next one is asJavaMutable().
Here’s an example that demonstrates the immutable Java List:
@Test(expected = UnsupportedOperationException.class)
public void givenParams_whenVavrListConverted_thenException() {
java.util.List<String> javaList
= List.of("Java", "Haskell", "Scala").asJava();
javaList.add("Python");
assertEquals(4, javaList.size());
}
As the List is immutable performing any modification on it throws an UnsupportedOperationException.
We can also get a mutable List by invoking the asJavaMutable() method on List.
Here’s how we do it:
@Test
public void givenParams_whenVavrListConvertedToMutable_thenRetunMutableList() {
java.util.List<String> javaList = List.of("Java", "Haskell", "Scala")
.asJavaMutable();
javaList.add("Python");
assertEquals(4, javaList.size());
}
5. Conversion Between Vavr Objects
Similar to conversion between Java to Vavr and vice-versa, we can convert a Value type in Vavr to other Value types. This conversion feature helps conversion between the Vavr objects when there is a need.
For example, we have a List of items, and we want to filter the duplicates while preserving the order. In this case, we would need a LinkedHashSet. Here’s an example that demonstrates the use case:
List<String> vavrList = List.of("Java", "Haskell", "Scala", "Java");
Set<String> linkedSet = vavrList.toLinkedSet();
assertEquals(3, linkedSet.size());
assertTrue(linkedSet instanceof LinkedHashSet);
There are many other methods available in the Value interface which help us to convert collections to different types depending on the use cases.
A full list of the APIs can be found here.
6. Conclusion
In this article, we’ve learned about conversion between Vavr and Java collection types.
The complete source code for all the examples in this article can be found over on Github.