1

Whilst trying to use Vavr's immutable map (io.vavr.collection.HashMap) with the java.util.Map interface, I did not manage to get the code to compile - at least not by using the .of() static method in io.vavr.collection.HashMap.

In essence this is the Maven dependency I am using:

<dependency>
    <groupId>io.vavr</groupId>
    <artifactId>vavr</artifactId>
    <version>0.9.2</version>
</dependency>

with Java 1.8

And this is the code:

import io.vavr.collection.HashMap;

import java.util.Map;

public class EntityKeyMap {

    public static final Map<String, String> map = 
            HashMap.of("key1", "val1", "key2", "val2", "key3", "val3");

    private EntityKeyMap() {
    }
}

This is the error I am getting:

Incompatible types. Required Map but 'of' was inferred to HashMap: no instance(s) of type variable(s) K, V exist so that HashMap conforms to Map

Any ideas how you can assign an instance of io.vavr.collection.HashMap to java.util.Map? Is that even possible?

According to io.vavr.collection.HashMap documentation it implements the java.util.Map interface:

https://static.javadoc.io/io.vavr/vavr/0.9.2/io/vavr/collection/HashMap.html

There are some examples on the web where it seems to be possible, like on this blog where you can find this code:

Map<String, String> map1
  = HashMap.of("key1", "val1", "key2", "val2", "key3", "val3");
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
gil.fernandes
  • 12,978
  • 5
  • 63
  • 76

2 Answers2

4

Vavr's HashMap doesn't implement JDK's Map interface. The Map interface it implements is vavr's own Map interface.

In contrast with JDK's Map, vavr's Map represents an immutable map, HashMap being an efficient persistent map implementation based on Hash array mapped trie.

The most fundamental difference between the JDK Map interface and the vavr Map interface is that the JDK map has methods that mutate the map's internal state, while vavr's methods always return a new Map instance (or the same instance in case the map didn't change).

Compare JDK's Map.put vs vavr's Map.put method signatures.

JDK Map.put:

V put(K key, V value)

Associates the specified value with the specified key in this map (optional operation). If the map previously contained a mapping for the key, the old value is replaced by the specified value. (A map m is said to contain a mapping for a key k if and only if m.containsKey(k) would return true.)
Returns: the previous value associated with key, or null if there was no mapping for key. (A null return can also indicate that the map previously associated null with key, if the implementation supports null values.)

vavr Map.put:

Map<K,V> put(K key, V value)

Associates the specified value with the specified key in this map. If the map previously contained a mapping for the key, the old value is replaced by the specified value.
Returns: A new Map containing these elements and that entry.

If you need a JDK Map, you can convert the vavr map with Map.toJavaMap, but that will create a full copy of the map contents, as the mutable nature of the JDK map is incompatible with the immutable approach of vavr.

Nándor Előd Fekete
  • 6,988
  • 1
  • 22
  • 47
2

There is the toJavaMap method exactly for this purpose:

Converts this Vavr Map to a java.util.Map while preserving characteristics like insertion order (LinkedHashMap) and sort order (SortedMap).

import io.vavr.collection.HashMap;

public class VavrPlayground {

   public static final HashMap<String, String> map =
       HashMap.of("key1", "val1", "key2", "val2", "key3", "val3");

   public void EntityKeyMap() {
      java.util.Map<String, String> jMap = map.toJavaMap();
   }

}
Eirini Graonidou
  • 1,506
  • 16
  • 24