Java basic skills: several postures of List to Map List

Continue to create, accelerate growth! This is the 4th day of my participation in the "Nuggets Daily New Plan · June Update Challenge", click to view the details of the event

Today, I will introduce a practical little knowledge point, how to convert List toMap<Object, List<Object>>

1. Basic writing

The first introduction is of course the most common and intuitive way of writing, and of course any restricted way of writing

// 比如将下面的列表,按照字符串长度进行分组
List<String> list = new ArrayList<>();
list.add("hello");
list.add("word");
list.add("come");
list.add("on");
Map<Integer, List<String>> ans = new HashMap<>();

for(String str: list) {
    List<String> sub = ans.get(str.length());
    if(sub == null) {
        sub = new ArrayList<>();
        ans.put(str.length(), sub);
    }
    sub.add(str);
}
System.out.println(ans);
复制代码

For jdk8+, the content in the above for loop can Map.computeIfAbsentbe replaced with the following:

for (String str : list) {
    ans.computeIfAbsent(str.length(), k -> new ArrayList<>()).add(str);
}
复制代码

Of course, since it is already jdk1.8, with the stream processing of Stream, the above step can be simplified, as follows

Map<Integer, List<String>> ans = list.stream().collect(Collectors.groupingBy(String::length));
复制代码

2. General approach

The above is for a specific list, for business development and transformation, then we will try to build a general tool class next

The knowledge point we mainly use here is generics, and an important point is how to get the key in the Map

For the writing method of jdk < 1.8, the acquisition posture of the key is defined through the interface

public static <K, V> Map<K, List<V>> toMapList(List<V> list, KeyFunc<V, K> keyFunc) {
    Map<K, List<V>> result = new HashMap<>();
    for (V item: list) {
        K key = keyFunc.getKey(item);
        if (!result.containsKey(key)) {
            result.put(key, new ArrayList<>());
        }
        result.get(key).add(item);
    }
    return result;
}

public static interface KeyFunc<T, K> {
    K getKey(T t);
}
复制代码

Use the demo as follows

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("hello");
    list.add("word");
    list.add("come");
    list.add("on");
    Map<Integer, List<String>> res = toMapList(list, new KeyFunc<String, Integer>() {
        @Override
        public Integer getKey(String s) {
            return s.length();
        }
    });
    System.out.println(res);
}
复制代码

Next, let's take a look at the writing method after jdk1.8, combined with stream + function method to achieve

public static <K, V> Map<K, List<V>> toMapList(List<V> list, Function<V, K> func) {
    return list.stream().collect(Collectors.groupingBy(func));
}
复制代码

The corresponding usage is as follows

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("hello");
    list.add("word");
    list.add("come");
    list.add("on");
    Map<Integer, List<String>> res = toMapList(list, (Function<String, Integer>) String::length);
    System.out.println(res);
}
复制代码

3. Tools

The previous section introduced the implementation of generic conversion tool classes based on generics + jdk8 Stream + function methods. Next, let's summarize and output a tool class that is applicable to 1.8 and later.

/**
 * List<V>转换为Map<K, List<V>> 特点在于Map中的value,是个列表,且列表中的元素就是从原列表中的元素
 *
 * @param list
 * @param func 基于list#item生成Map.key的函数方法
 * @param <K>
 * @param <V>
 * @return
 */
public static <K, V> Map<K, List<V>> toMapList(List<V> list, Function<V, K> func) {
    return list.stream().collect(Collectors.groupingBy(func));
}

/**
 * List<I>转换为Map<K, List<V>> 特点在于Map中的value是个列表,且列表中的元素是由list.item转换而来
 *
 * @param list
 * @param keyFunc 基于list#item生成的Map.key的函数方法
 * @param valFunc 基于list#item转换Map.value列表中元素的函数方法
 * @param <K>
 * @param <I>
 * @param <V>
 * @return
 */
public static <K, I, V> Map<K, List<V>> toMapList(List<I> list, Function<I, K> keyFunc, Function<I, V> valFunc) {
    return list.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valFunc, Collectors.toList())));
}
复制代码

4.Guava HashMultimap extended knowledge points

Finally, let's introduce an extended knowledge point. The Gauva toolkit provides a HashMultimaptool class. Its use posture is no different from our usual Map, but it should be noted that its value is a collection

List<String> list = new ArrayList<>();
list.add("hello");
list.add("word");
list.add("come");
list.add("on");
list.add("on");
HashMultimap<Integer, String> map = HashMultimap.create();
for (String item: strList) {
    map.put(item.length(), item);
}
System.out.println(map);
复制代码

The actual output is as follows, which verifies that the value is actually a set (there is only one on, if it is our tool class above, it will output two)

{2=[on], 4=[word, come], 5=[hello]}
复制代码

A grey contact

It is better to have no books than no books. The above content is purely from one family. Due to limited personal ability, there are unavoidable omissions and mistakes. If you find bugs or have better suggestions, you are welcome to criticize and correct them. Thank you very much.

Guess you like

Origin juejin.im/post/7104267494537297933