Spark学习之SparkSQL

SparkSQL

1、SparkSql初识案例 :WordCount
  • spark sql处理数据的步骤
  • 1、读取数据源
  • 2、将读取到的DF注册成一个临时视图
  • 3、使用sparkSession的sql函数,编写sql语句操作临时视图,返回的依旧是一个DataFrame
  • 4、将结果写出到hdfs上
import org.apache.spark.SparkContext
import org.apache.spark.sql.{DataFrame, Dataset, Row, SaveMode, SparkSession}object Demo1WordCount {def main(args: Array[String]): Unit = {//创建编写spark sql的环境val sparkSession: SparkSession = SparkSession/*** 用于创建或配置 SparkSession 实例的一个构建器(Builder)模式的应用* 使用 SparkSession.builder(),你可以链式地设置各种配置选项,* 并最终通过调用 .getOrCreate() 方法来获取一个 SparkSession 实例。*/.builder()// 执行模式:本地执行.master("local")// 名称.appName("sql语法风格编写WordCount")// 获取SparkSession.builder()创建的 SparkSession 实例.getOrCreate()/*** spark sql是spark core的上层api,如果要想使用rdd的编程* 可以直接通过sparkSession获取SparkContext对象*/val context: SparkContext = sparkSession.sparkContext//spark sql的核心数据类型是DataFrame(注意与RDD的区别)val df1: DataFrame = sparkSession.read.format("csv") // 读取csv格式的文件,但是实际上这种做法可以读取任意分隔符的文本文件.option("sep", "\n") //指定读取数据的列与列之间的分隔符.schema("line STRING") // 指定表的列字段 包括列名和列数据类型// 读取文件数据.load("spark/data/wcs/words.txt")//    println(df1)//查看DataFrame的数据内容//    df1.show()//查看表结构//    df1.printSchema()/*** sql语句是无法直接作用在DataFrame上面的* 需要提前将要使用sql分析的DataFrame注册成一张表(临时视图)*///老版本的做法将df注册成一张表//    df1.registerTempTable("wcs")df1.createOrReplaceTempView("wcs")/*** 编写sql语句作用在表上* sql语法是完全兼容hive语法*/val df2: DataFrame = sparkSession.sql("""|select|t1.word,|count(1) as counts|from(|select|explode(split(line,'\\|')) as word|from wcs) t1 group by t1.word|""".stripMargin)//    df2.show()//通过观察源码发现,DataFrame底层数据类型其实就是封装了DataSet的数据类型// 对DataFrame或Dataset进行重分区,Spark将这个DataFrame或Dataset的数据重新分配到1个分区中。val resDS: Dataset[Row] = df2.repartition(1)/*** 将计算后的DataFrame保存到本地磁盘文件中*/resDS.write.format("csv") //默认的分隔符是英文逗号//      .option("sep","\t").mode(SaveMode.Overwrite) // 如果想每次覆盖之前的执行结果的话,可以在写文件的同时指定写入模式,使用模式枚举类.save("spark/data/sqlout1") // 保存的路径其实是指定的一个文件夹}
}

DataFrame DSL

Spark SQL中的DataFrame DSL(Domain Specific Language,领域特定语言)是一种用于处理DataFrame的编程风格,它允许开发者以命令式的方式,通过调用API接口来操作DataFrame。这种风格**介于代码和纯SQL之间,**提供了一种更加灵活和强大的数据处理方式。

DataFrame DSL(Domain Specific Language,领域特定语言)中的API接口是一系列用于操作DataFrame的函数和方法。

1、DSL处理WordCount
import org.apache.spark.sql.{DataFrame, SaveMode, SparkSession}object Demo2DSLWordCount {def main(args: Array[String]): Unit = {//创建SparkSession对象val sparkSession: SparkSession = SparkSession.builder().master("local").appName("DSL语法风格编写spark sql").getOrCreate()val df1: DataFrame = sparkSession.read.format("csv").schema("line STRING").option("sep", "\n").load("spark/data/wcs/words.txt")/*** 如果要想使用DSL语法编写spark sql的话,需要导入两个隐式转换*///将sql中的函数,封装成spark程序中的一个个的函数直接调用,以传参的方式调用import org.apache.spark.sql.functions._//主要作用是,将来可以在调用的函数中,使用$函数,将列名字符串类型转成一个ColumnName类型//而ColumnName是继承自Column类的import sparkSession.implicits._//老版本聚合操作//    df1.select(explode(split($"line","\\|")) as "word")//      .groupBy($"word")//      .count().show()//新版本聚合操作// .as("word") == as "word" val resDF: DataFrame = df1.select(explode(split($"line", "\\|")) as "word").groupBy($"word").agg(count($"word") as "counts")resDF// 重分区.repartition(1).write.format("csv").option("sep","\t").mode(SaveMode.Overwrite).save("spark/data/sqlout2")}
}
2、DSLApi
import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.{DataFrame, SaveMode, SparkSession, expressions}object Demo3DSLApi {def main(args: Array[String]): Unit = {//创建SparkSession对象val sparkSession: SparkSession = SparkSession.builder().config("spark.sql.shuffle.partitions","1").master("local").appName("DSL语法风格编写spark sql").getOrCreate()/*** 如果要想使用DSL语法编写spark sql的话,需要导入两个隐式转换*///将sql中的函数,封装成spark程序中的一个个的函数直接调用,以传参的方式调用import org.apache.spark.sql.functions._//主要作用是,将来可以在调用的函数中,使用$函数,将列名字符串类型转成一个ColumnName类型//而ColumnName是继承自Column类的import sparkSession.implicits._/*** 读取json数据文件,转成DF* 读取json数据的时候,是不需要指定表结构,可以自动根据json的键值来构建DataFrame*///老版本的读取json数据的方式
//        val df1: DataFrame = sparkSession.read
//          .format("json")
//          .load("spark/data/students.json")val df1: DataFrame = sparkSession.read// 由于是json数据,数据中就有它们的列名,所以无需再为它们设置列名.json("spark/data/students.json")//默认显示20行数据//    df1.show()//传入要查看的行数//    df1.show(100)//传入第二个参数 truncate = false,观察的更加详细,默认每一列只会保留20个字符
//        df1.show(10,truncate = false)/*** DSL语法的第一个函数 select* 类似于纯sql语法中的select关键字,传入要查询的列*/
//    select name,clazz from xxx;df1.select("name","age").show()df1.select($"name", $"age").show()//查询每个学生的姓名,原本的年龄,年龄+1df1.select("name", "age").show()/*** 与select功能差不多的查询函数* 如果要以传字符串的形式给到select的话,并且还想对列进行表达式处理的话,可以使用selectExpr函数*/df1.selectExpr("name", "age", "age+1 as new_age").show()//如果想要使用select函数查询的时候对列做操作的话,可以使用$函数将列变成一个对象df1.select($"name", $"age", $"age" + 1 as "new_age").show()/*** DSL语法函数:where* === : 类似于sql中的= 等于某个值* =!= : 类似于sql中的!=或者<>  不等于某个值*/df1.where("gender='男'").show()df1.where("gender='男' and substring(clazz,0,2)='理科'").show()//TODO 建议使用隐式转换中的功能进行处理过滤,$"gender",将gender转换成一个ColumnName类对象//过滤出男生且理科的df1.where($"gender" === "男" and substring($"clazz",0,2) === "理科").show()//过滤出女生且理科的df1.where($"gender" =!= "男" and substring($"clazz",0,2) === "理科").show()/*** DSL语法函数:groupBy** 非分组字段是无法出现在select查询语句中的*///查询每个班级的人数df1.groupBy("clazz").agg(count("clazz") as "counts").show()/*** DSL语法函数:orderBy*/df1.groupBy("clazz").agg(count("clazz") as "counts").orderBy($"counts".desc).show(3)/*** DSL语法函数: join*/val df2: DataFrame = sparkSession.read.format("csv").option("sep", ",")
//      .schema("sid STRING,subject_id STRING,score INT").schema("id STRING,subject_id STRING,score INT").load("spark/data/score.txt")// 关联的字段名不一样的情况
//    df2.join(df1,$"id" === $"sid","inner")
//      .select("id","name","age","gender","clazz","subject_id","score")
//      .show(10)// 关联的字段名一样的情况df2.join(df1,"id").select("id","name","age","gender","clazz","subject_id","score").show(10)//如果关联的字段名一样且想使用其他连接方式的话,可以将字段名字用Seq()传入,同时可以传连接方式df2.join(df1, Seq("id"),"left").select("id","name","age","gender","clazz","subject_id","score").show(10)/*** DSL语法函数: 开窗* 无论是在纯sql中还是在DSL语法中,开窗是不会改变原表条数*///计算每个班级总分前3的学生//纯sql的方式实现
//    df1.createOrReplaceTempView("students")
//    df2.createOrReplaceTempView("scores")
//    sparkSession.sql(
//      """
//        |select
//        |*
//        |from
//        |(
//        |select t1.id,
//        |t2.name,
//        |t2.clazz,
//        |t1.sumScore,
//        |row_number() over(partition by t2.clazz order by t1.sumScore desc) as rn
//        |from
//        |(
//        | select id,
//        |        sum(score) as sumScore
//        | from
//        |   scores
//        | group by id) t1
//        |join
//        | students t2
//        |on(t1.id=t2.id)) tt1 where tt1.rn<=3
//        |""".stripMargin).show()//DSL语法实现df2.groupBy("id") //根据学号分组.agg(sum("score") as "sumScore") // 计算每个人总分.join(df1,"id") // 与学生信息表关联,得到班级列// over 不要写成 over().select($"id",$"name",$"clazz",$"sumScore",row_number() over Window.partitionBy("clazz").orderBy($"sumScore".desc) as "rn").where($"rn" <= 3)
//      .repartition(1).write.format("csv").mode(SaveMode.Overwrite).save("spark/data/sqlout3")}
}
3、SourceApi
import org.apache.spark.sql.{DataFrame, SaveMode, SparkSession}object Demo4SourceAPI {def main(args: Array[String]): Unit = {val sparkSession: SparkSession = SparkSession.builder().master("local").appName("data source api").config("spark.sql.shuffle.partitions", "1").getOrCreate()/*** 导入隐式转换你*/import org.apache.spark.sql.functions._import sparkSession.implicits._/*** ==========================================读写csv格式的数据==========================================* 可以读取使用分隔符分开的数据文件,例如.txt文件* 默认切分的分隔符为 ","*///如果是直接调用csv函数读取数据的话,无法做表结构的设置val df1: DataFrame = sparkSession.read.csv("spark/data/test1.csv")//使用format的形式读取数据的同时可以设置表结构val df2: DataFrame = sparkSession.read.format("csv").schema("id STRING,name STRING,age INT").load("spark/data/test1.csv")df2.show()val df3: DataFrame = sparkSession.read.format("csv").schema("id STRING,name STRING,age INT,gender STRING,clazz STRING").option("sep", ",").load("spark/data/students.txt")df3.createOrReplaceTempView("students")val resDF1: DataFrame = sparkSession.sql("""|select|clazz,|count(1) as counts|from students|group by clazz|""".stripMargin)//以csv格式写出到磁盘文件夹中resDF1.write.format("csv")//      .option("sep",",")// 模式为覆盖写.mode(SaveMode.Overwrite).save("spark/data/sqlout4")/*** ==========================================读写json格式的数据==========================================* 对数据进行读取时,无需为其字段命名,会用它的键值作为列名*/val df5: DataFrame = sparkSession.read.json("spark/data/students.json")df5.groupBy("age").agg(count("age") as "counts").write.json("spark/data/sqlout5")/*** ==========================================读写parquet格式的数据==========================================** parquet格式的文件存储,是由【信息熵】决定的* 存储有大量重复数据时,数据量比一般存储要少*/val df6: DataFrame = sparkSession.read.json("spark/data/students2.json")//以parquet格式写出去df6.write.parquet("spark/data/sqlout7")//    读取parquet格式的数据val df4: DataFrame = sparkSession.read.parquet("spark/data/sqlout7/part-00000-23f5482d-74d5-4569-9bf4-ea0ec91e86dd-c000.snappy.parquet")df4.show()/*** ==========================================读写orc格式的数据==========================================* 存储大量重复的数据时,数据量最少* 最常使用*/val df7: DataFrame = sparkSession.read.json("spark/data/students2.json")df7.write.orc("spark/data/sqlout8")sparkSession.read.orc("spark/data/sqlout8/part-00000-a33e356c-fd1f-4a5e-a87f-1d5b28f6008b-c000.snappy.orc").show()/*** ==========================================读写jdbc格式的数据==========================================**/sparkSession.read.format("jdbc").option("url", "jdbc:mysql://192.168.128.100:3306/studentdb?useUnicode=true&characterEncoding=UTF-8&useSSL=false").option("dbtable", "studentdb.jd_goods").option("user", "root").option("password", "123456").load().show(10,truncate = false)}
}
4、RDD到DataFrame的类型转换
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{DataFrame, Row, SparkSession}object Demo5RDD2DataFrame {def main(args: Array[String]): Unit = {val sparkSession: SparkSession = SparkSession.builder().master("local").appName("rdd与df之间的转换").config("spark.sql.shuffle.partitions", "1").getOrCreate()//通过SparkSession获取sparkContext对象val sparkContext: SparkContext = sparkSession.sparkContext//作用1:使用$函数,将字符串转换成列名对象//作用2:可以在不同的数据结构之间转换import sparkSession.implicits._/*** spark core的核心数据结构是:RDD* spark sql的核心数据结构是DataFrame*/// RDD->DataFrame  .toDFval linesRDD: RDD[String] = sparkContext.textFile("spark/data/students.txt")val stuRDD: RDD[(String, String, String, String, String)] = linesRDD.map((line: String) => {line.split(",") match {case Array(id: String, name: String, age: String, gender: String, clazz: String) =>(id, name, age, gender, clazz)}})val resRDD1: RDD[(String, Int)] = stuRDD.groupBy(_._5).map((kv: (String, Iterable[(String, String, String, String, String)])) => {(kv._1, kv._2.size)})val df1: DataFrame = resRDD1.toDFval df2: DataFrame = df1.select($"_1" as "clazz", $"_2" as "counts")/***用于打印出该数据集的架构(schema)信息。* 架构是指数据集中各列的名称、数据类型以及可能的元数据(如是否为空、默认值等)。*/df2.printSchema()// DataFrame->RDD  .rddval resRDD2: RDD[Row] = df2.rdd//TODO RDD[Row]类型数据的取值resRDD2.map((row:Row)=>{val clazz: String = row.getAs[String]("clazz")//TODO 这里的泛型最好使用Integer与在DataFrame中的类型保持一致val counts: Integer = row.getAs[Integer]("counts")s"班级:$clazz, 人数:$counts"}).foreach(println)resRDD2.map {case Row(clazz:String, counts:Integer)=>s"班级:$clazz, 人数:$counts"}.foreach(println)}
}
5、开窗函数
import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}/*** 开窗:over*  聚合开窗函数:sum  count  lag(取上一条)  lead(取后一条)*  排序开窗函数:row_number rank dense_rank**  练习开窗的题目: DSL语法去做*    统计总分年级排名前十学生各科的分数*    统计每科都及格的学生*    统计总分大于年级平均分的学生*    统计每个班级的每个名次之间的分数差*/
object Demo6WindowFun {def main(args: Array[String]): Unit = {val sparkSession: SparkSession = SparkSession.builder().master("local").appName("rdd与df之间的转换").config("spark.sql.shuffle.partitions", "1").getOrCreate()/*** 导入隐式转换你*/import org.apache.spark.sql.functions._import sparkSession.implicits._/*** 读取三个数据文件* 补充:* agg() 方法允许你指定一个或多个聚合函数,这些函数将应用于 DataFrame 的列上,以生成聚合后的结果。* withColumn():用于向 DataFrame 中添加新的列或替换已存在的列。*/val studentsDF: DataFrame = sparkSession.read.format("csv").schema("id STRING,name STRING,age INT,gender STRING,clazz STRING").load("spark/data/students.txt")
//    studentsDF.show()val scoresDF: DataFrame = sparkSession.read.format("csv").schema("id STRING,subject_id STRING,score INT").load("spark/data/score.txt")
//    scoresDF.show()val subjectsDF: DataFrame = sparkSession.read.format("csv").schema("subject_id STRING,subject_name STRING,subject_score INT").load("spark/data/subject.txt")
//    subjectsDF.show()//统计总分年级排名前十学生各科的分数/*** dense_rank() 在处理并列排名时不会留下空缺。* 即,如果有两行或多行具有相同的排名依据值,它们将被赋予相同的排名,* 并且下一个排名的值会紧接着这些并列排名的最后一个值*/val resDS1: Dataset[Row] = scoresDF.join(studentsDF, "id").withColumn("sumScore", sum("score") over Window.partitionBy("id")).withColumn("rn", dense_rank() over Window.partitionBy(substring($"clazz", 0, 2)).orderBy($"sumScore".desc)).where($"rn" <= 10).limit(120)//统计每科都及格的学生val resDS2: Dataset[Row] = scoresDF.join(subjectsDF, "subject_id").where($"score" >= $"subject_score" * 0.6).withColumn("jigeCount", count(expr("1")) over Window.partitionBy($"id")).where($"jigeCount" === 6)//统计总分大于年级平均分的学生,TODO(注:需要对年级进行分组:文科/理科,对班级字段进行切分)val resDS3: Dataset[Row] = scoresDF.join(studentsDF, "id").withColumn("sumScore", sum($"score") over Window.partitionBy($"id")).withColumn("avgScore", avg($"sumScore") over Window.partitionBy(substring($"clazz", 0, 2))).where($"sumScore" > $"avgScore")//统计每个班级的每个名次之间的分数差scoresDF.join(studentsDF, "id")// 使用分组来求解,只查询分组中的字段和聚合后的新字段,而不会出现有科目编号,使一个学生有六组数据的情况.groupBy("id", "clazz").agg(sum("score") as "sumScore")// |1500100001|文科六班|     406|, 只会输出 groupby 的字段和新添加的字段.withColumn("rn", row_number() over Window.partitionBy($"clazz").orderBy($"sumScore".desc)).withColumn("beforeSumScore", lag($"sumScore", 1, 750) over Window.partitionBy($"clazz").orderBy($"sumScore".desc)).withColumn("cha", $"beforeSumScore" - $"sumScore").show()}
}
6、提交到yarn上进行执行

idea里面将代码编写好打包上传到集群中运行,上线使用

import org.apache.spark.sql.{DataFrame, SparkSession}object Demo8SubmitYarn {def main(args: Array[String]): Unit = {val sparkSession: SparkSession = SparkSession.builder()
//      .master("local").appName("提交到yarn 计算每个班级的人数")//TODO 设置shuffle分区数(进行重分区),参数设置的优先级:代码优先级 > 命令优先级 > 配置文件优先级// 分区数越多,并行度越高,理论上可以加快数据处理速度。但过高的分区数也可能导致调度和管理开销增加,反而降低性能。.config("spark.sql.shuffle.partitions", "1").getOrCreate()import org.apache.spark.sql.functions._import sparkSession.implicits._val df1: DataFrame = sparkSession.read.format("csv").schema("id STRING,name STRING,age INT,gender STRING,clazz STRING")// TODO 下面函数中的路径为HDFS上的路径(图为要打包到集群中运行).load(args(0))val df2: DataFrame = df1.groupBy($"clazz").agg(count($"id") as "counts")df2.show()df2.write// 将数据存储到HDFS上的路径.csv(args(1))}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/48400.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++基础语法:STL之容器(6)--序列容器中的forward_list

前言 "打牢基础,万事不愁" .C的基础语法的学习 引入 序列容器的学习.以<C Prime Plus> 6th Edition(以下称"本书")内容理解 本书中容器内容不多只有几页.最好是有数据结构方面的知识积累,如果没有在学的同时补上 上一篇C基础语法:链表和数据结…

Linux系统命令:监控 CPU 性能的工具mpstat详解

目录 一、概述 二、语法和使用 1、基本语法 2、常用选项 三、安装 mpstat 1、Debian&#xff08;如 Ubuntu&#xff09;的系统安装 2、CentOS 或 Fedora系统的安装 &#xff08;1&#xff09;安装指令 &#xff08;2&#xff09;安装操作 3、使用 四、示例 1. 查看…

【人工智能】Python实现文本转换为语音:使用gTTS库实现

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、引言二、准备工作三、使用gTTS实现文本转换为语音详细步骤 四、人工智能与TTS技术五、总结 一、引言 文本转换为语音&#xff08;Text-to-Speech&#xff0c;简称TTS&#xff09;技术是人工智能的重要组成部分&#xf…

Unity UGUI 之 Canvas画布

本文仅作学习笔记与交流&#xff0c;不作任何商业用途 本文包括但不限于unity官方手册&#xff0c;唐老狮&#xff0c;麦扣教程知识&#xff0c;引用会标记&#xff0c;如有不足还请斧正 1.UGUI是什么 首先官方手册导向了这两个连接&#xff0c;里面是ugui的基本教程 帆布 |U…

【C语言】 链表实现学生管理系统(堆区开辟空间)

总体思路都能写出来&#xff0c;问题是感觉稍微比之前的麻烦一些&#xff0c;在刚开始创建结构体的时候&#xff0c;并没有去按照链表的思路去写&#xff0c;导致写成了顺序表&#xff0c;后面就一直纠结空间怎么开辟。 链表是由一个头节点和其它申请出来的小节点连起来的&…

统计一个页面用到的html,css,js

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>统计html</title><style>* {margin: …

Web前端知识视频教程分享(四) jQuery

资料下载地址: https://545c.com/f/45573183-1334618723-883dfe?p7526 (访问密码: 7526)

【有效验证】解决SQLyog连接MYSQL的错误 1251 - Client does not support

目录 一、原因分析&#xff1a; 二、进入到mysql 三、查看当前加密方式 四、更改加密方式 五、查看是否成功 前言&#xff1a;使用一个开源软件使用sqlyog、navcat都报1251错误&#xff0c;网上都是提示升级客户端&#xff0c;还有一种就是修改mysql配置。本文就是修改配置…

虚拟机OP的LAN网口设置

问题&#xff1a;unraid通过虚拟机安装OP&#xff0c;然而一个网口连接路由器&#xff0c;总是无法为其他设备提供DHCP&#xff0c;导致无法使用。 一、虚拟机OP配置 二、OP内部配置 对于Lan网口&#xff0c;启用强制&#xff0c;这样可以防止OP被网口接的路由器产生冲突 三、…

认识接口测试

接口测试为什么重要&#xff1f; 我相信你一定听说过这样一句话&#xff1a;“测试要尽早介入&#xff0c;测试进行得越早&#xff0c;软件开发的成本就越低&#xff0c;就越能更好地保证软件质量。” 但是如何尽早地进入测试&#xff0c;作为软件测试的你&#xff0c;是不是…

web自动化测试

自动化测试理论 UI&#xff1a;User Interface&#xff08;用户接口-用户界面&#xff09;&#xff0c;主要包括&#xff1a;app、web ui自动化测试&#xff1a;使用工具或代码执行用例的过程 什么样的项目适合做自动化 1、需要回归测试项目&#xff08;甲方自营项目、金融、…

IPS(入侵防御)和AS(反病毒)的总结

目录 IAE引擎 深度行为检测技术 深度包检测 DPI 深度包检测的分类 1&#xff0c;基于特征字的检测技术 2&#xff0c;基于应用网关的检测技术 3&#xff0c;基于行为模式的检测技术 深度流检测 DFI DPI和DFI的对比 IPS&#xff08;入侵防御&#xff09; 入侵检测 IDS 入侵防御…

分布式锁的使用场景是什么?有哪些实现方法?

在单体架构中&#xff0c;多个线程都是属于同一个进程的&#xff0c;所以在线程并发执行遇到资源竞争时&#xff0c;可以利用ReentrantLock、synchronized等技术来作为锁&#xff0c;来控制共享资源的使用。 而在分布式架构中&#xff0c;多个线程是可能处于不同进程中的&…

5.串口通信

串口的介绍 UART&#xff08;通用异步收发器&#xff09;是一种双向、串行、异步的通信总线&#xff0c;仅用一根数据接收线&#xff08;RX&#xff09;和一根数据发送线&#xff08;TX&#xff09;就能实现全双工通信 R&#xff1a;Receiver(接收)&#xff0c;T&#xff1a;T…

mac os 去除压缩包下的__MACOSX

mac os 去除压缩包下的__MACOSX 步骤 步骤 在mac上压缩文件后执行 zip -d xxx.zip "__MACOSX*"

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 中文分词模拟器(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线…

Vue的动态和异步组件:提升应用性能的利器

引言 在现代前端应用开发中,组件化是构建用户界面的主流方式。Vue.js 作为一个流行的前端框架,提供了强大的组件系统。Vue 不仅支持静态组件的使用,还支持动态组件和异步组件。动态组件允许我们在运行时动态地切换不同的组件,而异步组件则允许我们在需要时才加载组件。这两…

浅谈Canal原理

canal [kə’nl]&#xff0c;译意为水道/管道/沟渠&#xff0c;主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据 订阅 和 消费。应该是阿里云DTS&#xff08;Data Transfer Service&#xff09;的开源版本。 Canal与DTS提供的功能基本相似&#xff1a; 基于…

vue2学习笔记9 - 通过观察vue实例中的data,理解Vue中的数据代理

接着上一节&#xff0c;学一学vue中的数据代理。学vue这几天&#xff0c;最大的感受就是&#xff0c;名词众多&#xff0c;听得发懵。。不过&#xff0c;深入理解之后&#xff0c;其实说得都是一回事。 在Vue中&#xff0c;数据代理是指在实例化Vue对象时&#xff0c;将data对…

神经网络模型实现(训练、测试)

目录 一、神经网络骨架&#xff1a;二、卷积操作&#xff1a;三、卷积层&#xff1a;四、池化层&#xff1a;五、激活函数&#xff08;以ReLU为例&#xff09;&#xff1a;六、模型搭建&#xff1a;七、损失函数、梯度下降&#xff1a;八、模型保存与加载&#xff1a;九、模型训…