文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

随着Java8成为主流,人们开始在所有地方使用流api(Steams),甚至在那些有点生硬的情景下(也就是,夸张一点说,完全疯了).举个例子,看下面mykong的这篇展示如何将Map的entry set流转化为一个键的List和一个值的List的文章: http://www.mkyong.com/java8/java-8-convert-map-to-list

发布在mykong.com上的代码分两个步骤来做这件事:

package com.mkyong.example;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class ConvertMapToList {
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();
        map.put(10, "apple");
        map.put(20, "orange");
        map.put(30, "banana");
        map.put(40, "watermelon");
        map.put(50, "dragonfruit");

        System.out.println("\n1. Export Map Key to List...");

        List<Integer> result = map.entrySet().stream()
                .map(x -> x.getKey())
                .collect(Collectors.toList());

        result.forEach(System.out::println);

        System.out.println("\n2. Export Map Value to List...");

        List<String> result2 = map.entrySet().stream()
                .map(x -> x.getValue())
                .collect(Collectors.toList());

        result2.forEach(System.out::println);
    }
}
第 1 段(可获 0.96 积分)

你自己的代码通常不应该这样做.首先,如果你不介意遍历map两次,那么最简单的聚集map的键和值的方式应该是下面这样的:

List<Integer> result1 = new ArrayList<>(map.keySet());
List<String> result2 = new ArrayList<>(map.values());

在这个特定例子中绝对没有必要采用Java 8的streams.上面的代码实现显得既简洁又高效.

别把所有问题都塞给Java 8 Streams.

但是如果你真的想要使用streams,那么我个人倾向于在一行代码做这件事的解决方案.在这个特定的例子中没必要遍历Map两次.举例来说,你可以使用jOOλ的 Tuple.collectors()方法做这件事,这个方法将两个聚集器合并成一个新的聚集器 ,而这个新的collector会返回单独集合组成的元组.

第 2 段(可获 1.7 积分)

代码比上面的描述说的更清楚.Mykong.com的那段代码可以替换为如下代码:

Tuple2<List<Integer>, List<String>> result = 
map.entrySet()
    .stream()
    .collect(Tuple.collectors(
        Collectors.mapping(Entry::getKey, Collectors.toList()),
        Collectors.mapping(Entry::getValue, Collectors.toList())
    ));

在这儿唯一跟jOOλ有关的代码是这个调用:Tuple.collectors(),这个调用在将键和值聚集为list之前,合并了多个在Map entries上进行映射的标准JDK聚集器.

 

第 3 段(可获 0.64 积分)

打印上面结果时,你会得到:

([50, 20, 40, 10, 30], [dragonfruit, orange, watermelon, apple, banana])

即一个包含结果list的元组.

再简化下,不使用Java 8 Stream API,使用 jOOλ的Seq(针对串行流),那么我们可以写下如下更短的代码作为替代:

Tuple2<List<Integer>, List<String>> result = 
Seq.seq(map)
   .collect(
        Collectors.mapping(Tuple2::v1, Collectors.toList()),
        Collectors.mapping(Tuple2::v2, Collectors.toList())
   );

相比前一个例子,此处的 Collectable.collect(Collector, Collector)提供了非常棒的语法糖

第 4 段(可获 0.59 积分)

文章评论