Stream编程

一 Stram编程

主要是 回忆 jdk1.8提供的stream编程中一些方法,还有scala中类似流的操作,以及kafka中无状态操作算子的区分,老是区分不了,今天写一篇文章,加深自己的印象,首先介绍jdk1.8新特性stream

所谓jdk1.8出现的Stream就是对一些集合功能的增强,他可以对集合中的元素做到细粒度的控制扫描,将其转换为类似一条流水线,并对其进行处理,stream的出现简化了java开发,并且提高了并发效率吗,一般流分为中间操作和终端操作

1.1 jdk1.8 stream中间操作

limit : 截短流 参数是一个long 返回值也是流

import java.util.Arrays;
import java.util.stream.Collectors;

public class StreamDemo01 {
    public static void main(String[] args) {
        
        Arrays.asList("GX", "XM", "ZS", "LS", "WL")
                //将集合转换为流
                .stream()
                //保留前2位元素
                .limit(2)
                //调用collect 将流转换为一个集合  类似于终端操作   Collectors.toList() 
                .collect(Collectors.toList())
                // 遍历打印输出 
                .forEach(System.out::println);
    }
}

filter:将流中元素以某种规则过滤 参数是元素 返回值是一个boolean

distinct: 过滤重复元素

public class StreamDemo01 {
    public static void main(String[] args) {

        Arrays.asList("GX", "XM", "ZS", "LS", "WL","ZS")
                //将集合转换为流
                .stream()
                //以某种规则进行过滤
                .filter(v->v.startsWith("Z"))
                //过滤重复元素
                .distinct()
                //调用collect 将流转换为一个集合  类似于终端操作   Collectors.toList()
                .collect(Collectors.toList())
                // 遍历打印输出
                .forEach(System.out::println);
    }
}

map : 将流中的元素转换为另外一种元素 参数是一个function

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamDemo01 {
    public static void main(String[] args) {

        List<Student> list = new ArrayList<>();
        list.add(new Student("GX", "123456"));
        list.add(new Student("ZS", "123456"));
        list.add(new Student("LS", "123456"));
        list.add(new Student("XM", "123456"));
        list.stream()
                // 将流中的元素 一种泛型转换为另外一种泛型  Student-> String
                .map(Student::getName)
                .collect(Collectors.toList())
                .forEach(System.out::println);
    }
}

class Student {

    private String name;
    private String password;

    public Student() {
    }

    public Student(String name, String password) {
        this.name = name;
        this.password = password;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

flatMap 扁平化 参数描述 T->Stream<R> 将T 变为一个R 并且是以R为泛型的Stream 最后返回

 public static void main(String[] args) {

        Arrays.asList("Hello word", "Hello Kafka", "Hello Hadoop", "Hello SpringBoot", "Hello Spark","Hello Zookeeper")
                //将集合转换为流
                .stream()
                // 将字符串以某种规则转换为一个数组并且返回 返回值是一个流
                .flatMap(v->{
                    String[] split = v.split(" ");
                    return Arrays.stream(split);
                })
                //过滤重复元素
                .distinct()
                //调用collect 将流转换为一个集合  类似于终端操作   Collectors.toList()
                .collect(Collectors.toList())
                // 遍历打印输出
                .forEach(System.out::println);
    }

1.2 scala中的Stream编程

scala中的匿名函数在最后奉献

java 中的Stream 编程来于scala ,scala是一种多范式的编程语言,其中内置了23个函数对象,scala是一门纯面向对象的语言,可以运行在jvm虚拟机中,也可以运行在js中 scala中Stream 类似于java

map java中的map将一个元素变为另外一种元素,内部可以进行细粒度的控制,当然scala中也是

package demo02

object StreamDemo02 {

  def main(args:(Array[String])): Unit ={

    val arr = Array(1,2,3,4)
    arr.map(k=>k*2).foreach(k=>println(k))

  }

}

scala中的wordCount 实现单词技术功能

package demo02

object StreamDemo02 {

  def main(args:(Array[String])): Unit ={

    val arr = Array("Hello word","Hello spring","Hello SpringCloud","Hello SpringBoot","Hello SpringMvc")
    //展开  将每个字符串按空格进行切分
    arr.flatMap(k=>k.split(" "))
      //然后映射成一个map集合
      .map(k=>(k,1))
      // 根据键进行分组操作   参数是一个function对象
      .groupBy((k:(String,Int))=>k._1)
      // 将分组后再次映射为一个map
      .map(k=>(k._1,k._2.length))
      .foreach(k=>println(k))
  }

}

1.3kafka中无状态操作算子

kafka作为流数据处理平台 其中最重要的`Kafka Straming 是一个用于构建应用程序和微服务的客户端库,其中的输入和输出数据存储在Kafka集群中。它结合了在客户端编写和部署标准Java和Scala应用程序的简单性,以及Kafka服务器端集群技术的优点

简单回顾一下 kafka Streaming

kafkaStraming 消费者从topic拉取数据到缓冲区,然后topology 会从缓冲区中拉去属于自己的数据,每一个topology由多个processor 构成 形成有向无环图,其中有state store 用来存放计算的中间结果,最后通过计算的结果将数据通过Stream thread 中的producer写出到topic中

无状态操作算子 指的是没有数据产生 状态指的是数据 一般是 Kstream -> Kstream

无状态的操作算子, 指进行数据转换操作时不会涉及到状态的管理

  • Branch

    KStream ----> KStream[]

    KStream<String, String>[] kStreams = stream.branch(
                    (k, v) -> v.startsWith("A"),   // stream: A开头
                    (k, v) -> true                 // 其它数据
            );
    kStreams[0].foreach((k,v) -> System.out.println(k + "\t"+v));
    
  • Filter

    KStream —> KStream

    保留符合Boolean条件(true)的数据

    stream
         .filter((k,v) -> v.startsWith("H"))
        .foreach((k,v) -> System.out.println(k+"\t"+v));
    
  • filterNot

    KStream → KStream

    KTable → KTable

    保留不符合Boolean条件的数据

    stream
        .filterNot((k,v) -> v.startsWith("H"))
        .foreach((k,v) -> System.out.println(k+"\t"+v));
    
  • FlatMap

    KStream → KStream

    将一个Record展开为0-n个Record

    stream
         .flatMap((k,v) -> Arrays.asList(
              new KeyValue<String,String>(k,v.toUpperCase()+"!"),
              new KeyValue<String,String>(k,v.toLowerCase()+"?")))
        .foreach((k,v) -> System.out.println(k +"\t" + v));
    
  • flatMapValues

    KStream → KStream

    将一个Record的value展开为1到N个新的value(key不变)

    stream
                    // null Hello World
                    //--------------------
                    // null Hello
                    // null World
        .flatMapValues((v) -> Arrays.asList(v.split(" ")))
        .foreach((k, v) -> System.out.println(k + "\t" + v));
    
  • Foreach

    KStream → void (终止操作)

    对KStream中的数据进行迭代遍历,无返回值

    stream
                    // null Hello World
                    //--------------------
                    // null Hello
                    // null World
        .flatMapValues((v) -> Arrays.asList(v.split(" ")))
        .foreach((k, v) -> System.out.println(k + "\t" + v));
    
  • GroupBy

    KStream → KGroupedStream

    根据指定的信息 进行分区操作,注意分组时会进行Shuffle(洗牌)

    //============================groupBy===================================
    stream
                    // null Hello World
                    //--------------------
                    // null Hello
                    // null World
         .flatMapValues((v) -> Arrays.asList(v.split(" ")))
        .groupBy((k,v) -> v)
        .count()
        .toStream()
        .foreach((k,v) -> System.out.println(k+"\t"+v));
    //======================================================================
    
  • GroupByKey

    KStream → KGroupedStream

    根据已存在的key值进行分区操作(洗牌)

    stream
                    // null Hello World
                    //--------------------
                    // null Hello
                    // null World
        .flatMapValues((v) -> Arrays.asList(v.split(" ")))
        .map((k,v) -> new KeyValue<String,Long>(v,1L))
        .groupByKey(Grouped.with(Serdes.String(),Serdes.Long()))
        .count()
        .toStream()
        .foreach((k,v) -> System.out.println(k+"\t"+v));
    
  • Map

    KStream → KStream

    将一个流中的一条数据映射为另外一条数据

  • mapValues

    类似于map操作,不同key不可变,V可变

    stream
        // null Hello World
        //--------------------
        // null Hello
        // null World
        .flatMapValues((v) -> Arrays.asList(v.split(" ")))
        .map((k,v) -> new KeyValue<>(v,1L))
        .mapValues(v -> v = v+1)
        .foreach((k,v) -> System.out.println(k+"\t"+v));
    
  • Merge

    KStream → KStream

    将两个流合并为一个大流

    KStream<String, String>[] streams = stream
                    .branch(
                            (k, v) -> v.startsWith("A"),
                            (k, v) -> v.startsWith("B"),
                            (k, v) -> true
                    );
            streams[0].merge(streams[2])
                    .foreach((k,v) -> System.out.println(k+"\t"+v));
    
  • Peek

    KStream → KStream

    探针(调试程序): 不会改变数据流内容

    stream.peek((k,v) -> System.out.println(k+"\t"+v));
    
  • Print

    等价于foreach((key, value) -> System.out.println(key + ", " + value))

    stream.print(Printed.toSysOut());
    
  • SelectKey

    KStream → KStream

    给流中的数据,分配新的k值(k变,v不变)

    stream.selectKey((k,v) -> "Hello:").print(Printed.toSysOut());
    
  • Table to Stream

    KTable → KStream

    table.toStream();
    

补充!关于 scala 中高阶函数

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值