實(shí)戰(zhàn)小技巧19:List轉(zhuǎn)Map List的幾種姿勢

今天介紹一個實(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或者有更好的建議,歡迎批評指正喷面,不吝感激

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末星瘾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子惧辈,更是在濱河造成了極大的恐慌琳状,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盒齿,死亡現(xiàn)場離奇詭異念逞,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)边翁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門翎承,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人符匾,你說我怎么就攤上這事叨咖。” “怎么了啊胶?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵甸各,是天一觀的道長。 經(jīng)常有香客問我焰坪,道長趣倾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任某饰,我火速辦了婚禮儒恋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘露乏。我一直安慰自己碧浊,他們只是感情好涂邀,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布瘟仿。 她就那樣靜靜地躺著,像睡著了一般比勉。 火紅的嫁衣襯著肌膚如雪劳较。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天浩聋,我揣著相機(jī)與錄音观蜗,去河邊找鬼。 笑死衣洁,一個胖子當(dāng)著我的面吹牛墓捻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播坊夫,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼砖第,長吁一口氣:“原來是場噩夢啊……” “哼撤卢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起梧兼,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤放吩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后羽杰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體渡紫,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年考赛,在試婚紗的時候發(fā)現(xiàn)自己被綠了惕澎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡欲虚,死狀恐怖集灌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情复哆,我是刑警寧澤欣喧,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站梯找,受9級特大地震影響唆阿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锈锤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一驯鳖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧久免,春花似錦浅辙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至呼巴,卻和暖如春泽腮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背衣赶。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工诊赊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人府瞄。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓碧磅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鲸郊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容