(0)Java 8 stream、map、flatmap

目录

 

1、Stream

1.1 知识点-并行处理(parallel)

1.2 知识点- ::用法(双冒号)

1.3 知识点-Collectors

2、map和flatmap的区别


1、Stream

      参考:Java 8 新特性

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。我的理解就是流作为一个输入经过一系列的过程之后产生中间流,最后由最后的操作(terminal operation)产生结果。

什么是 Stream? 

Stream(流)是一个来自数据源的元素队列并支持聚合操作

  • 元素 是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
  • 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
  • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

和以前的Collection操作不同, Stream操作还有两个基础的特征:

  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现

1.1 知识点-并行处理(parallel)

原代码:
for (Map<String, Object> allUser : allUserList) {
    String userIdkey = allUser.get("user_id").toString();
    ...//io数据库操作
}

java8代码:
allUserList.stream().parallel().forEach(allUser -> {
    String userIdkey = allUser.get("user_id").toString();
    ...//io数据库操作
});

总结:

使用java8的parallel可以加快统计速度,从运行结果的对比可以看出,使用parallel后jdbc连接会存在多个并行执行,执行效率和机器配置内存等相关。

测试:

原始写法:

        List<String> al = Arrays.asList("a", "b", "c", "d");
        al.forEach(x -> {
            System.out.println(Thread.currentThread().getId() + "   x");
        });

结果:

 

 新写法:

        List<String> al = Arrays.asList("a", "b", "c", "d");
        al.stream().parallel().forEach(x -> {
            System.out.println(Thread.currentThread().getId() + "   x");
        });

 结果:

1.2 知识点- ::用法(双冒号)

JDK8中有双冒号的用法,就是把方法当做参数传到stream内部,使stream的每个元素都传入到该方法里面执行一下。

说白了就是 使用 ::(例如 System.out::println)代替lamda表达式。eg:

al.stream().parallel().forEach(System.out::println);

老式代码:

public class AcceptMethod {

 

    public static void  printValur(String str){

        System.out.println("print value : "+str);

    }

 

    public static void main(String[] args) {

        List<String> al = Arrays.asList("a","b","c","d");

        for (String a: al) {

            AcceptMethod.printValur(a);

        }

      //下面的for each循环和上面的循环是等价的 

        al.forEach(x->{

            AcceptMethod.printValur(x);

        });

    }

}

java 8 双冒号:
 

public class MyTest {

    public static void  printValur(String str){

        System.out.println("print value : "+str);

    }

 

    public static void main(String[] args) {

        List<String> al = Arrays.asList("a", "b", "c", "d");

        al.forEach(AcceptMethod::printValur);

        //下面的方法和上面等价的

        Consumer<String> methodParam = AcceptMethod::printValur; //方法参数

        al.forEach(x -> methodParam.accept(x));//方法执行accept

    }

}

上面的运行结果都是一样

1.3 知识点-Collectors

Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:

List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
 
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));

-----------------------------------------------------------

collect: 收集器

Collector 作为 collect 方法的参数

Collector 本身是一个接口,它是一个可变的汇聚操作,作用是将输入元素累积到一个可变的结果容器中(如ArrayList 是一个可变容器);(可选操作)它会在所有元素都处理完毕后,将累积的结果转换为一个最终的表示。它支持串行和并行两者方式。

Collectors 本身提供了关于 Collector 的常见汇聚实现,Collectors 本身是一个工厂.

......

参考:Collector接口详解以及实现类

2、map和flatmap的区别

参考:java8 Stream map和flatmap的区别

map:

map的作用很容易理解就是对rdd之中的元素进行逐一进行函数操作映射为另外一个rdd。

map函数会对每一条输入进行指定的操作,然后为每一条输入返回一个对象。

flatMap:

flatMap的操作是将函数应用于rdd之中的每一个元素,将返回的迭代器的所有内容构成新的rdd。通常用来切分单词

flatMap函数则是两个操作的集合——正是“先映射后扁平化”。


flatMap的用法和含义住要通过一个案例来讲解,

案例:对给定单词列表 ["Hello","World"],你想返回列表["H","e","l","o","W","r","d"]

第一种方式-map

String[] words = new String[]{"Hello","World"};
List<String[]> a = Arrays.stream(words)
        .map(word -> word.split(""))
        .distinct()
        .collect(Collectors.toList());
a.forEach(System.out::print);

代码输出为:[Ljava.lang.String;@12edcd21[Ljava.lang.String;@34c45dca (返回一个包含两个String[]的list)

        这个实现方式是由问题的,传递给map方法的lambda为每个单词生成了一个String[](String列表)。因此,map返回的流实际上是Stream<String[]> 类型的。你真正想要的是用Stream<String>来表示一个字符串。

      下方图是上方代码stream的运行流程:

 

第二种方式-flatMap(对流扁平化处理)

String[] words = new String[]{"Hello","World"};
List<String> a = Arrays.stream(words)
        .map(word -> word.split(""))
        .flatMap(Arrays::stream)
        .distinct()
        .collect(Collectors.toList());
a.forEach(System.out::println);

或者

String[] words = new String[]{"Hello","World"};
        List<String> collect = Stream.of(words).map(i -> i.split("")).flatMap(Stream::of).collect(Collectors.toList());

或者

List<String> collect = Stream.of(words).flatMap(word -> Stream.of(word.split(""))).collect(Collectors.toList());

结果输出:

        使用flatMap方法的效果是,各个数组并不是分别映射一个流,而是映射成流的内容,所有使用map(Array::stream)时生成的单个流被合并起来,即扁平化为一个流。

    下图是运用flatMap的stream运行流程,

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值