Java中List轉Map List實現的幾種姿勢
今天介紹一個實用的小知識點,如何將List轉為Map<Object, List<Object>>
1. 基本寫法
最開始介紹的當然是最常見、最直觀的寫法,當然也是任何限制的寫法
// 比如將下面的列表,按照字符串長度進行分組 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);
對於jdk8+,上面for循環中的內容可以利用Map.computeIfAbsent來替換,具體寫法如下
for (String str : list) { ans.computeIfAbsent(str.length(), k -> new ArrayList<>()).add(str); }
當然既然已經是jdk1.8瞭,借助Stream的流處理,可以將上面的更一步進行簡化,如下
Map<Integer, List<String>> ans = list.stream().collect(Collectors.groupingBy(String::length));
2. 通用方法
上面是針對特定的列表,針對業務進行開發轉換,那麼我們接下來嘗試構建一個通用的工具類
這裡我們主要借助的知識點就是泛型,一個重要的點就是如何獲取Map中的key
對於jdk < 1.8的寫法,通過接口來定義實現key的獲取姿勢
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); }
使用demo如下
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); }
接下來再看一下jdk1.8之後的寫法,結合stream + 函數方法來實現
public static <K, V> Map<K, List<V>> toMapList(List<V> list, Function<V, K> func) { return list.stream().collect(Collectors.groupingBy(func)); }
其對應的使用方式則如下
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. 工具類
上一節介紹瞭基於泛型 + jdk8 Stream + 函數方法來實現通用轉換工具類的實現姿勢,接下來我們小結一下,輸出一個適用於1.8之後的工具類
/** * 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擴展知識點
最後再介紹一個擴展知識點,Gauva工具包中提供瞭一個HashMultimap的工具類,他的使用姿勢和我們平常的Map並無差別,但是需要在註意的是,它的value是個集合
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);
實際輸出如下,驗證瞭value實際上是個集合(on隻有一個,如果是我們上面的工具類,會輸出兩個)
{2=[on], 4=[word, come], 5=[hello]}
到此這篇關於Java中List轉Map List實現的幾種姿勢的文章就介紹到這瞭,更多相關Java中List轉Map List內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 一篇文章帶你瞭解Java Stream流
- java8如何用Stream查List對象某屬性是否有重復
- java使用stream判斷兩個list元素的屬性並輸出方式
- 關於List、Map、Stream初始化方式
- Java8 將一個List<T>轉為Map<String,T>的操作