全国咨询热线:400-009-1906

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

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

更多精彩内容以及学习资料,尚学堂论坛bbs.bjsxt.com免费下载。

发布在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 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 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 result2 = map.entrySet().stream()                 .map(x -> x.getValue())                 .collect(Collectors.toList());          result2.forEach(System.out::println);     } } 

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

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

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

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

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

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

 Tuple2, List> 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聚集器.

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

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

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

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

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

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

更多精彩内容以及学习资料,尚学堂论坛bbs.bjsxt.com免费下载。