1047521767 发表于 2021-11-22 20:13

数据结构+spark

                              数据结构+spark
赫夫曼树
赫夫曼编码-数据压缩
压缩
解码
数据的加载和保存
加载数据
保存数据
MySql
Hive
SparkStreaming
背压机制
wordcount
RDD队列
自定义数据采集器
赫夫曼树
1)给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree), 还有的书翻译为霍夫曼树。

2)赫夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

构成赫夫曼树的步骤:

1)从小到大进行排序, 将每一个数据,每个数据都是一个节点 , 每个节点可以看成是一颗最简单的二叉树

2)取出根节点权值最小的两颗二叉树

3)组成一颗新的二叉树, 该新的二叉树的根节点的权值是前面两颗二叉树根节点权值的和

4)再将这颗新的二叉树,以根节点的权值大小 再次排序, 不断重复 1-2-3-4 的步骤,直到数列中,所有的数据都被处理,就得到一颗赫夫曼树
package huffmantree;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class HuffmanTree {

    public static void main(String[] args) {
        int []arr={13,7,8,3,29,6,1};

        Node root = createHuffmanTree(arr);
        root.preOrder();
    }


    //创建赫夫曼树的方法

    public static Node createHuffmanTree(int[]arr ) {
        //1、遍历arr数组
        //2、将arr的每个元素构成一个node
        //3、将Node放入到ArrayList中
        List<Node> nodes = new ArrayList<>();
        for (int value : arr) {
            nodes.add(new Node(value));
        }

        while (nodes.size() > 1) {
            //排序 从小到大
            Collections.sort(nodes);

            //取出根节点权值最小的两颗二叉树
            //(1)取出权值最小的节点(二叉树)
            Node leftNode = nodes.get(0);
            //(2)取出权值第二小的节点(二叉树)

            Node rightNode = nodes.get(1);

            //(3)构建一颗新的二叉树
            Node parent = new Node(leftNode.value + rightNode.value);
            parent.left = leftNode;
            parent.right = rightNode;

            //(4)从ArrayList中删除处理过的二叉树
            nodes.remove(leftNode);
            nodes.remove(rightNode);

            //(5)将parent加入到nodes
            nodes.add(parent);
        }

        return nodes.get(0);
    }
}

//创建节点类
//为了让Node 对象支持排序Collections集合排序
//让Node 实现Comparable接口

class Node implements Comparable<Node>{
    int value;//节点权值
    Node left;//指向左子节点
    Node right;//指向右子节点
    public Node(int value){
        this.value=value;
    }

    //前序遍历
    public void preOrder(){
        System.out.println(this.value);
        if(this.left!=null)this.left.preOrder();
        if(this.right!=null)this.right.preOrder();

    }

  @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }

    @Override
    public int compareTo(Node o) {
        //从小到大排序
        return this.value-o.value;
    }
}
赫夫曼编码-数据压缩
1)赫夫曼编码也翻译为哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式, 属于一种程序算法

2)赫夫曼编码是赫哈夫曼树在电讯通信中的经典的应用之一。

3)赫夫曼编码广泛地用于数据文件压缩。其压缩率通常在20%~90%之间

4)赫夫曼码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,称之为最佳编码
https://img-blog.csdnimg.cn/d0941f5c55604ee8b0f54a52651dde25.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAU3dlZXTjgr3lsJvmmbTlpKnjgaVf,size_14,color_FFFFFF,t_70,g_se,x_16

压缩
package huffmantree.huffmancode;

import java.util.*;
public class HuffmanCode {
    public static void main(String[] args) {

        String content="i like like like java do you like a java";
        byte[]contentBytes=content.getBytes();

        byte[] huffmanCodesBytes = huffmanZip(contentBytes);
        System.out.println("压缩后的结果是:"+Arrays.toString(huffmanCodesBytes));

    }

    //使用一个方法,将前面的方法封装起来,便于调用
    private static byte[] huffmanZip(byte[]bytes){
        //
        List<Node>node=getNodes(bytes);
        //更具node创建赫夫曼树
        Node huffmanTreeRoot=createHuffmanTree(node);

        Map<Byte, String> huffmanCodes = getCodes(huffmanTreeRoot);
        //根据生成的赫夫曼编码,压缩得到压缩后的赫夫曼编码字节数组
        return zip(bytes,huffmanCodes);

    }

    /**
     *
     * @param bytes 这是原始的字符串对应的byte[]
     * @param huffmanCodes 生成的赫夫曼编码map
     * @return 返回赫夫曼编码处理后的byte []
     */
    private static byte[] zip(byte[]bytes,Map<Byte,String> huffmanCodes){
        //1、利用huffmanCodes 将 bytes 转成 赫夫曼编码对应的字符串
        StringBuilder stringBuilder = new StringBuilder();
        for(byte b:bytes){
            stringBuilder.append(huffmanCodes.get(b));
        }

        //将stringBuilder转成 byte[]
        //统计返回 byte[] huffmanCode 长度
        int len;
        if(stringBuilder.length()%8==0){
            len=stringBuilder.length()/8;
        }else{
            len =stringBuilder.length()/8+1;
        }

        //创建 存储压缩后的byte数组
        byte[]huffmanCodeBytes=new byte;
        int index=0;

        byte[]by=new byte;
        for (int i = 0; i < stringBuilder.length(); i+=8) {//每八位对应一个byte,所以步长+8
            String strByte;
            if(i+8>stringBuilder.length()){//不够八位
                strByte=stringBuilder.substring(i);
            }else {
                strByte = stringBuilder.substring(i, i + 8);
            }
            //将strByte 转换成一个 byte ,放入到 huffmanCodeBytes
            huffmanCodeBytes=(byte) Integer.parseInt(strByte,2);
            index++;

        }
        return huffmanCodeBytes;

    }

    private static List<Node>getNodes(byte[]bytes){
        ArrayList <Node>nodes=new ArrayList<>();

        //遍历bytes,统计每一个byte出现次数->map
        Map<Byte,Integer> counts=new HashMap<>();
        for(byte b:bytes){
            Integer count=counts.getOrDefault(b,0);
            counts.put(b,count+1);
        }

        //把每一个键值对转成一个Node对象,并加入到nodes集合
        for(Map.Entry<Byte,Integer>entry:counts.entrySet()){
            nodes.add(new Node(entry.getKey(),entry.getValue()));
        }


        return nodes;
    }

    //创建对应的赫夫曼树
    private static Node createHuffmanTree(List<Node>nodes){
        while(nodes.size()>1){
            //从小到大
            Collections.sort(nodes);

            Node left=nodes.get(0);
            Node right=nodes.get(1);

            Node parent=new Node(null,left.weight+right.weight);
            parent.left=left;
            parent.right=right;

            nodes.remove(left);
            nodes.remove(right);

            nodes.add(parent);
        }
        return nodes.get(0);
    }

    //生成赫夫曼树对应的赫夫曼编码
    static Map<Byte,String> huffmanCodes=new HashMap<>();
    //static StringBuilder stringBuilder=new StringBuilder();

    private static Map<Byte,String>getCodes(Node root){
        if(root==null){
            return null;
        }
        //处理root的左子树
        getCodes(root.left,"0",new StringBuilder());
        //处理root的右子树
        getCodes(root.right,"1",new StringBuilder());
        return huffmanCodes;
    }

    /**
     * 功能:将传入的node结点的赫夫曼编码得到,并放入到huffmanCodes集合
     * @param node 传入结点
     * @param code 路径:左子结点是0,右子结点是1
     * @param stringBuilder 用于拼接路径
     */
    private static void getCodes(Node node,String code,StringBuilder stringBuilder){
        StringBuilder stringBuilder2 = new StringBuilder(stringBuilder);
        //将code加到stringBuilder2
        stringBuilder2.append(code);
        if(node!=null){//如果node==null 不处理
            //判断当前node 是叶子结点还是非叶子结点
            if(node.data==null){//非叶子结点
                //递归处理
                //向左
                getCodes(node.left,"0",stringBuilder2);
                //向右递归
                getCodes(node.right,"1",stringBuilder2);
            }else{//说明是一个叶子结点
                //表示找到某个叶子结点的最后
                huffmanCodes.put(node.data,stringBuilder2.toString());

            }
        }

    }




}
class Node implements Comparable<Node>{
    Byte data;//存放数据
    int weight;//权值,表示字符出现的次数

    Node left;
    Node right;

    public Node(Byte data, int weight) {
        this.data = data;
        this.weight = weight;
    }


    @Override
    public int compareTo(Node o) {
        //从小到大排序
        return this.weight-o.weight;
    }

    @Override
    public String toString() {
        return "Node{" +
                "data=" + data +
                ", weight=" + weight +
                '}';
    }

    //前序遍历
    public void preOrder(){
        System.out.println(this);
        if(this.left!=null)this.left.preOrder();
        if(this.right!=null)this.right.preOrder();
    }

}


https://img-blog.csdnimg.cn/1ea97053b3c0458989fe2f3a837b631f.png

解码
public class HuffmanCode {
    public static void main(String[] args) {

        String content = "i like like like java do you like a java";
        byte[] contentBytes = content.getBytes();

        byte[] huffmanCodesBytes = huffmanZip(contentBytes);
        System.out.println("压缩后的结果是:" + Arrays.toString(huffmanCodesBytes));

        byte[] sourceBytes = decode(huffmanCodes, huffmanCodesBytes);
        System.out.println("原来的字符串:"+new String(sourceBytes));


    }

    //编写一个方法,完成对压缩数据的解码

    /**
     *
     * @param huffmanCodes 赫夫曼编码 map
     * @param huffmanBytes 赫夫曼编码得到字节数组
     * @return 就是原来的字符串对应的数组
     */
    private static byte[]decode(Map<Byte,String>huffmanCodes,byte[]huffmanBytes){

        //先得到huffmanBytes对应的二进制的字符串,

        StringBuilder stringBuilder = new StringBuilder();
        //将byte数组转成二进制的字符串
        for (int i = 0; i < huffmanBytes.length; i++) {
            byte b=huffmanBytes;
            //判断是不是最后一个字节
            boolean flag=(i==huffmanBytes.length-1);
            stringBuilder.append(byteToBitString(!flag,b));
        }
        System.out.println(stringBuilder);


        //把字符按串按照指定的赫夫曼编码进行解码
        //把赫夫曼编码表进行调换
        Map<String,Byte>map=new HashMap<>();

        for(Map.Entry <Byte,String>entry:huffmanCodes.entrySet()){
            map.put(entry.getValue(),entry.getKey());
        }

        //创建一个集合,存放byte
        List<Byte>list=new ArrayList<>();
        //i 可以理解成一个索引 扫描 stringBuilder
        for(int i=0;i<stringBuilder.length();){
            int count=1;//
            boolean flag=true;
            Byte b=null;
            while(flag){
                //取出一个字符
                String key=stringBuilder.substring(i,i+count);//i不懂,让count移动,知道匹配到一个字符
                b=map.get(key);
                if(b==null){//说明没有匹配到
                    count++;
                }else{
                    //匹配到
                    flag=false;
                }
            }
            list.add(b);
            i+=count;//i 直接移动到 count

        }
        //当for循环结束后 list中就存放了所有的字符
        //把list中的数据放入到byte[]并返回
        byte b[]=new byte;
        for (int i = 0; i <list.size() ; i++) {
            b=list.get(i);
        }
        return b;
    }


    //完成数据的解码
    //重写转成 赫夫曼编码对应的二进制字符串
    // 赫夫曼编码对应的二进制的字符串 =》 对照 赫夫曼编码

    /**
     * 将一个byte 转成一个二进制的字符串
     * @param flag 标识是否需要补高位 如果是true 表示需要补高位,如果是false表示不补
     * @param b 传入的byte
     * @return 是该b 对应的二进制的字符串,(注意是按补码返回)
     */
    private static String byteToBitString(boolean flag,byte b) {
        //使用变量保存 b
        int temp = b;//将b 转成int

        //如果是正数还需要补高位
        if(flag)
        temp |= 256;//按位与256 1 0000 0000 | 0000 0001 =》1 0000 0001

        String str = Integer.toBinaryString(temp);//返回的二进制的补码

        if(flag){
            return str.substring(str.length()-8);
        }else{
            return str;
        }

    }


https://img-blog.csdnimg.cn/a1178f1bc5f94775b6e51a3a7e6fddbc.png

数据的加载和保存
SparkSQL 提供了通用的保存数据和数据加载的方式。这里的通用指的是使用相同的 API,根据不同的参数读取和保存不同格式的数据,SparkSQL 默认读取和保存的文件格式 为 parquet

加载数据
spark.read.load 是加载数据的通用方法
csv format jdbc json load option options orc parquet schema
table text textFile

如果读取不同格式的数据,可以对不同的数据格式进行设定

scala> spark.read.format("…")[.option("…")].load("…")
➢ format("…"):指定加载的数据类型,包括"csv"、“jdbc”、“json”、“orc”、"parquet"和 “textFile”。

➢ load("…"):在"csv"、“jdbc”、“json”、“orc”、“parquet"和"textFile"格式下需要传入加载 数据的路径。 ➢ option(”…"):在"jdbc"格式下需要传入 JDBC 相应参数,url、user、password 和 dbtable 我们前面都是使用 read API 先把文件加载到 DataFrame 然后再查询,其实,我们也可以直 接在文件上进行查询: 文件格式.文件路径

scala>spark.sql(“select * from json./opt/module/data/user.json”).show

保存数据
df.write.save 是保存数据的通用方法
csv jdbc json orc parquet textFile… …


如果保存不同格式的数据,可以对不同的数据格式进行设定

scala>df.write.format("…")[.option("…")].save("…")
➢ format("…"):指定保存的数据类型,包括"csv"、“jdbc”、“json”、“orc”、"parquet"和 “textFile”。

➢ save ("…"):在"csv"、“orc”、"parquet"和"textFile"格式下需要传入保存数据的路径。

➢ option("…"):在"jdbc"格式下需要传入 JDBC 相应参数,url、user、password 和 dbtable 保存操作可以使用 SaveMode, 用来指明如何处理数据,使用 mode()方法来设置。 有一点很重要: 这些 SaveMode 都是没有加锁的, 也不是原子操作。

SaveMode 是一个枚举类,其中的常量包括:

Scala/Java Any Language Meaning

SaveMode.ErrorIfExists(default) “error”(default) 如果文件已经存在则抛出异常

SaveMode.Append “append” 如果文件已经存在则追加

SaveMode.Overwrite “overwrite” 如果文件已经存在则覆盖

SaveMode.Ignore “ignore” 如果文件已经存在则忽略

df.write.mode(“append”).json("/opt/module/data/output")

MySql
package sql

import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame, SaveMode, SparkSession}

object SparkSqlJDBC {

  def main(args: Array): Unit = {
    val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("sparkSQL")
    val spark: SparkSession =SparkSession.builder().config(sparkConf).getOrCreate()

    //读取mysql数据
    val df: DataFrame = spark.read
      .format("jdbc")
      .option("url", "jdbc:mysql://localhost:3306/jw?user=root&password=1234")
      .option("driver", "com.mysql.cj.jdbc.Driver")
      .option("password", "1234")
      .option("dbtable", "course")
      .load()

    df.show()

    //保存数据
    df.write
      .format("jdbc")
      .option("url", "jdbc:mysql://localhost:3306/test?user=root&password=1234")
      .option("driver", "com.mysql.cj.jdbc.Driver")
      .option("password", "1234")
      .option("dbtable", "course")
      .mode(SaveMode.Append)
      .save()


  }

}


Hive
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-hive_2.12</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
</dependency>

将 hive-site.xml 文件拷贝到项目的 resources 目录中,代码实现

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
    #显示表头
    <property>
        <name>hive.cli.print.header</name>
        <value>true</value>
    </property>

    <property>
        <name>hive.cli.print.current.db</name>
        <value>true</value>
    </property>

    <property>
        <name>javax.jdo.option.ConnectionURL</name>
        <value>jdbc:mysql://hadoop103:3306/metastore?createDatabaseIfNotExist=true</value>
        <description>JDBC connect string for a JDBC metastore</description>
    </property>

    <property>
        <name>javax.jdo.option.ConnectionDriverName</name>
        <value>com.mysql.jdbc.Driver</value>
        <description>Driver class name for a JDBC metastore</description>
    </property>

    <property>
        <name>javax.jdo.option.ConnectionUserName</name>
        <value>root</value>
        <description>username to use against metastore database</description>
    </property>

    <property>
        <name>javax.jdo.option.ConnectionPassword</name>
        #密码
        <value>123456</value>
        <description>password to use against metastore database</description>
    </property>
</configuration>
def main(args: Array): Unit = {
    val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("sparkSQL")
    val spark: SparkSession =SparkSession.builder().enableHiveSupport().config(sparkConf).getOrCreate()

    spark.sql("show tables").show()

  }

SparkStreaming
Spark Streaming 用于流式数据的处理。Spark Streaming 支持的数据输入源很多,例如:Kafka、 Flume、Twitter、ZeroMQ 和简单的 TCP 套接字等等。数据输入后可以用 Spark 的高度抽象原语 如:map、reduce、join、window 等进行运算。而结果也能保存在很多地方,如 HDFS,数据库等。

SparkStreaming 准实时(秒,分钟),微批次(时间) 的数据处理框架

DStream 就是对 RDD 在实时数据处理场景的一种封装。

背压机制
​ 为了更好的协调数据接收速率与资源处理能力,1.5 版本开始 Spark Streaming 可以动态控制 数据接收速率来适配集群数据处理能力。背压机制(即 Spark Streaming Backpressure): 根据 JobScheduler 反馈作业的执行信息来动态调整 Receiver 数据接收率。

​ 通过属性“spark.streaming.backpressure.enabled”来控制是否启用 backpressure 机制,默认值 false,即不启用。

wordcount
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.12</artifactId>
<version>3.0.0</version>
</dependency>


需求:使用 netcat 工具向 9999 端口不断的发送数据,通过 SparkStreaming 读取端口数据并 统计不同单词出现的次数

package sql

import org.apache.spark.SparkConf
import org.apache.spark.sql.SparkSession
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream}

object WordCount {
  def main(args: Array): Unit = {
    //创建环境对象
    val sparkConf = new SparkConf().setMaster("local[*]").setAppName("wordCont")
    //第一个参数表示环境配置
    //第二个参数表示批量处理的周期(采集周期)
    val ssc: StreamingContext =new StreamingContext(sparkConf,Seconds(3))

    //获取端口数据
    val lines: ReceiverInputDStream = ssc.socketTextStream("localhost", 9999)

    val words: DStream = lines.flatMap(_.split(" "))

    val wordToOne: DStream[(String, Int)] = words.map((_, 1))

    val wordToCount: DStream[(String, Int)] = wordToOne.reduceByKey(_ + _)

    wordToCount.print()

    wordToCount.saveAsTextFiles("datas/result")

    //由于SparkStreaming采集器是长期执行的任务 不能直接关闭
    //如果main方法执行完毕,应用程序也会自动结束,所以不能让main执行完毕

    //1、启动采集器
    ssc.start()
    //2、等待采集器的关闭
    ssc.awaitTermination()



  }


}
RDD队列
测试过程中,可以通过使用 ssc.queueStream(queueOfRDDs)来创建 DStream,每一个推送到 这个队列中的 RDD,都会作为一个 DStream 处理。

➢ 需求:循环创建几个 RDD,将 RDD 放入队列。通过 SparkStream 创建 Dstream,计算 WordCount
package streaming

import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
import org.apache.spark.streaming.dstream.{DStream, InputDStream}
import org.apache.spark.streaming.{Seconds, StreamingContext}

import scala.collection.mutable


object Queue {
  def main(args: Array): Unit = {
    //1.初始化 Spark 配置信息
    val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDDStream")
    //2.初始化 SparkStreamingContext
    val ssc: StreamingContext = new StreamingContext(conf, Seconds(4))
    //3.创建 RDD 队列
    val rddQueue: mutable.Queue] = new mutable.Queue]()
    //4.创建 QueueInputDStream
    val inputStream: InputDStream = ssc.queueStream(rddQueue,oneAtATime = false)
    //5.处理队列中的 RDD 数据
    val mappedStream: DStream[(Int, Int)] = inputStream.map((_,1))
    val reducedStream: DStream[(Int, Int)] = mappedStream.reduceByKey(_ + _)
    //6.打印结果
    reducedStream.print()
    //7.启动任务
    ssc.start()
    //8.循环创建并向 RDD 队列中放入 RDD
    for (i <- 1 to 5) {
      rddQueue += ssc.sparkContext.makeRDD(1 to 300, 10)
      Thread.sleep(2000)
    }
    ssc.awaitTermination()
  }

}
自定义数据采集器
package streaming

import org.apache.spark.SparkConf
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.dstream.ReceiverInputDStream
import org.apache.spark.streaming.receiver.Receiver
import org.apache.spark.streaming.{Seconds, StreamingContext}

import scala.util.Random

object DIY {
  def main(args: Array): Unit = {
    val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDDStream")
    val ssc: StreamingContext = new StreamingContext(conf, Seconds(4))

    val messageDS: ReceiverInputDStream = ssc.receiverStream(new MyReceiver())
    messageDS.print()



    ssc.start()
    ssc.awaitTermination()
  }

}

/**
* 自定义数据采集器
*/
class MyReceiver extends Receiver(StorageLevel.MEMORY_ONLY){

  private var flag=true;

  override def onStart(): Unit = {
    new Thread(new Runnable {
      override def run(): Unit = {
        while(flag){
          val message: String ="采集的数据为"+new Random().nextInt(10).toString
          store(message)
          Thread.sleep(500)
        }
      }
    }).start()

  }

  override def onStop(): Unit = {
    flag=false

  }
}
data:image/png;base64,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





页: [1]
查看完整版本: 数据结构+spark