“This is the second day of my participation in the November Gwen Challenge. See details of the event: The last Gwen Challenge 2021”.

In daily development, converting from one Map to another is a basic operation, so how do we implement this scenario? Is there a simpler way to do this?

Example scenario

Now let’s give a simple example

We want to convert a Map

to Map
,>
,>

Start by providing a public method to create a Map

private static <T> Map<String, T> newMap(String key, T val, Object... kv) {
    Map<String, T> ans = new HashMap<>(8);
    ans.put(key, val);
    for (int i = 0, size = kv.length; i < size; i += 2) {
        ans.put(String.valueOf(kv[i]), (T) kv[i + 1]);
    }
    return ans;
}
Copy the code

Method 1: Basic for loop conversion

This is the easiest way to think of and implement it, and it’s just a for loop

@Test
public void forEachParse(a) {
    Map<String, Integer> map = newMap("k".1."a".2."b".3);
    Map<String, String> ans = new HashMap<>(map.size());
    for (Map.Entry<String, Integer> entry: map.entrySet()) {
        ans.put(entry.getKey(), String.valueOf(entry.getValue()));
    }
    System.out.println(ans);
}
Copy the code

The advantages of this approach are obvious, easy to implement, intuitive business;

Disadvantages are poor reusability and large amount of code (compared to the following case)

Mode 2: streaming use of containers

Streaming operations are provided in jdk1.8, and transformations can be implemented in this way as well

@Test
public void stream(a) {
    Map<String, Integer> map = newMap("k".1."a".2."b".3);
    Map<String, String> ans = map.entrySet().stream().collect(
            Collectors.toMap(Map.Entry::getKey, s -> String.valueOf(s.getValue()), (a, b) -> a));
    System.out.println(ans);
}
Copy the code

The advantage of using stream is that it is chained and has less code. The disadvantage is that the reading experience will be worse than the above (of course, this depends on the individual, some friends are more used to reading this kind of chained code).

Method 3: Guava’s Trasform method

At the code level, the above two are not intuitive, but those of you familiar with Guava will probably be familiar with the following code

@Test
public void transfer(a) {
    Map<String, Integer> map = newMap("k".1."a".2."b".3);
    Map<String, String> ans =  Maps.transformValues(map, String::valueOf);
    System.out.println(ans);
}
Copy the code

The core logic is a single line maps.transformvalues (map, String::valueOf), which implements our map transformation requirements

The obvious advantage of this approach is that it is indirect and intuitive; Of course, the disadvantage is that you need to introduce guava and become familiar with guava

Finally, what is the purpose of this article?

We can use Guava’s maps.transformValues to implement map transformations, but what if we were to implement a utility class to support this scenario?

Just provide a conversion method?

Step 1: A generic transformation interface

public <K, T, V> Map<K, V> transform(Map<K, T> map) {}Copy the code

After defining the interface above, the natural drawback is the lack of a value conversion implementation

Step 2: Define the value conversion

The idea of the Function interface is used to define the transformation class

public <K, T, V> Map<K, V> transform(Map<K, T> map, Function<T, V> func) {}Copy the code

Jdk1.8 does not support functional programming, so how can we implement it?

At this time, compare the implementation of Guava, and then masturbate a knowledge point in hand

A gray contact information

All letter is better than no book, the above content, purely one’s words, due to the limited personal ability, it is hard to avoid omissions and mistakes, such as finding bugs or better suggestions, welcome criticism and correction, not grudging gratitude

  • Personal site: blog.hhui.top
  • Micro Blog address: Small Gray Blog
  • QQ: a gray /3302797840
  • Wechat official account: One Grey Blog