今天介紹一個實(shí)用的小知識點(diǎn),如何將List轉(zhuǎn)為Map<Object, List<Object>>
1. 基本寫法
最開始介紹的當(dāng)然是最常見池磁、最直觀的寫法奔害,當(dāng)然也是任何限制的寫法
// 比如將下面的列表,按照字符串長度進(jìn)行分組
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循環(huán)中的內(nèi)容可以利用Map.computeIfAbsent
來替換另假,具體寫法如下
for (String str : list) {
ans.computeIfAbsent(str.length(), k -> new ArrayList<>()).add(str);
}
當(dāng)然既然已經(jīng)是jdk1.8了僧须,借助Stream的流處理,可以將上面的更一步進(jìn)行簡化雅潭,如下
Map<Integer, List<String>> ans = list.stream().collect(Collectors.groupingBy(String::length));
2. 通用方法
上面是針對特定的列表,針對業(yè)務(wù)進(jìn)行開發(fā)轉(zhuǎn)換却特,那么我們接下來嘗試構(gòu)建一個通用的工具類
這里我們主要借助的知識點(diǎn)就是泛型扶供,一個重要的點(diǎn)就是如何獲取Map中的key
對于jdk < 1.8的寫法,通過接口來定義實(shí)現(xiàn)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之后的寫法裂明,結(jié)合stream + 函數(shù)方法來實(shí)現(xiàn)
public static <K, V> Map<K, List<V>> toMapList(List<V> list, Function<V, K> func) {
return list.stream().collect(Collectors.groupingBy(func));
}
其對應(yīng)的使用方式則如下
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. 工具類
上一節(jié)介紹了基于泛型 + jdk8 Stream + 函數(shù)方法來實(shí)現(xiàn)通用轉(zhuǎn)換工具類的實(shí)現(xiàn)姿勢椿浓,接下來我們小結(jié)一下,輸出一個適用于1.8之后的工具類
/**
* List<V>轉(zhuǎn)換為Map<K, List<V>> 特點(diǎn)在于Map中的value闽晦,是個列表扳碍,且列表中的元素就是從原列表中的元素
*
* @param list
* @param func 基于list#item生成Map.key的函數(shù)方法
* @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>轉(zhuǎn)換為Map<K, List<V>> 特點(diǎn)在于Map中的value是個列表,且列表中的元素是由list.item轉(zhuǎn)換而來
*
* @param list
* @param keyFunc 基于list#item生成的Map.key的函數(shù)方法
* @param valFunc 基于list#item轉(zhuǎn)換Map.value列表中元素的函數(shù)方法
* @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擴(kuò)展知識點(diǎn)
最后再介紹一個擴(kuò)展知識點(diǎn)仙蛉,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);
實(shí)際輸出如下夯巷,驗證了value實(shí)際上是個集合(on只有一個,如果是我們上面的工具類哀墓,會輸出兩個)
{2=[on], 4=[word, come], 5=[hello]}
一灰灰的聯(lián)系方式
盡信書則不如無書鞭莽,以上內(nèi)容,純屬一家之言麸祷,因個人能力有限澎怒,難免有疏漏和錯誤之處,如發(fā)現(xiàn)bug或者有更好的建議,歡迎批評指正喷面,不吝感激
- 個人站點(diǎn):https://blog.hhui.top
- 微博地址: 小灰灰Blog
- QQ: 一灰灰/3302797840
- 微信公眾號:*一灰灰blog