Spark 算子

目录

什么是Spark rdd算子

算子的分类

Transformation算子

Action算子

转换算子

Value类型

map

mapPartitions

mapPartitionsWithIndex

glom

groupBy

filter

sample

distinct

coalesce

sortBy

双Value类型

intersection

union

subtract

zip

K-V类型

partitionBy

reduceByKey

groupByKey

aggregateByKey

foldByKey

combineByKey

join

sortByKey

mapValues

cogroup

行动算子

reduce

collect

count

first

take

takeOrdered

aggregate

fold

countByValue

countByKey

foreach

save


什么是Spark rdd算子

算子:分布式对象上的API称之为算子

方法\函数:本地对象的API,叫做方法\函数

算子:分布式对象的API,叫做算子

算子的分类

rdd算子分为两类

  • Transformation:转换算子
  • Action:动作(行动)算子

Transformation算子

定义:RDD的算子,返回值仍旧是一个RDD的,称之为转换算子。
特征:这类算子是lazy 懒加载的,如果没有Action算子,Transformation算子是不工作的。

转换算子分为:Value类型、双Value类型和K-V类型。

Action算子

定义:返回值不是rdd的就是action算子。

对于这两类算子来说,Transformation算子,相当于在构建执行计划,action是一个指令让这个执行计划开始工作。如果没有action,Transformation算子之间的迭代关系,就是一个没有通电的流水线,只有action到来,这个数据处理流水线才开始工作。

转换算子

Value类型

map

将处理的数据逐条进行映射转换,这里的转换可以是类型的转换,也可以是值的转换。

 val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(
      List(1, 2, 3, 4)
    )
    val mapRDD = rdd.map(_ * 2)
    mapRDD.collect().foreach(println)
    /**
     * 2
     * 4
     * 6
     * 8
     * */

mapPartitions

以分区为单位对数据进行处理,这里的处理是指可以进行任意的处理,哪怕是过滤数据。

  val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(
      List(1, 2, 3, 4), 2
    )
    val mapRDD = rdd.mapPartitions(datas => datas.map(_ * 2))
    mapRDD.collect().foreach(println)

    /** *
     * 2
     * 4
     * 6
     * 8
     */

TIP:

1、会将整个分区的数据加载到内存,如果处理完不被释放,在内存较小并且数据量较大的情况下,容易出现内存溢出(OOM)

2、可以实现一些特殊功能,比如取每个分区中最大值,map无法实现

mapPartitionsWithIndex

类似于mapPartitions,比mapPartitions多一个参数来表示分区号

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(
      List(List(1, 2), List(3, 4))
    )
    val fmRDD = rdd.flatMap(
      list => {
        list
      }
    )
    fmRDD.collect().foreach(println)

    /**
     * 1
     * 2
     * 3
     * 4
     * */

当集合中的数据类型不同时,可以使用match case进行模式匹配,转换成集合类型。

val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
val rdd = sc.makeRDD(
    List(List(1, 2),3, List(3, 4))
)
val fmRDD = rdd.flatMap {
    case list: List[_] => list
    case d => List(d)
}
fmRDD.collect().foreach(println)
    /**
     * 1
     * 2
     * 3
     * 3
     * 4
     * */

glom

将RDD中每一个分区变成一个数组,数组中元素类型与原分区中元素类型一致。

  val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(
      List(1, 2, 3, 4), 2
    )
    val gRDD = rdd.glom()
    gRDD.collect().foreach(data => println(data.mkString(",")))

    /**
     * 1,2
     * 3,4
     * */

groupBy

根据指定的规则进行分组,分区默认不变,数据会被打乱(shuffle)。极限情况下,数据可能会被分到同一个分区中。一个分区可以有多个组,一个组只能在一个分区中。

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(
      List(1, 2, 3, 4), 2
    )

    // groupBy 会将数据源中的每一个数据进行分组判断,根据返回的分组key进行分组,相同的key值的数据会被放置在一个组中
    def groupFunction(num: Int): Int = {
      num % 2
    }

    val groupRDD = rdd.groupBy(groupFunction)
    groupRDD.collect().foreach(println)

    /**
     * (0,CompactBuffer(2, 4))
     * (1,CompactBuffer(1, 3))
     */

filter

根据指定的规则进行筛选过滤,符合规则的数据保留,不符合的丢弃。

当数据进行筛选过滤后,分区不变,但是分区内数据可能不均衡,导致数据倾斜。

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(
      List(1, 2, 3, 4), 2
    )
    val filterRDD = rdd.filter(_ % 2 == 1)
    filterRDD.collect().foreach(println)

    /**
     * 1
     * 3
     * */

sample

根据指定规则从数据集中采样数据。通过它可以找到数据倾斜的key。

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(
      List(1, 2, 3, 4), 2
    )
    println(rdd.sample(
      true,
      2
    ).collect().mkString((",")))

    /**
     *1,1,2,3,3,4,4
     * */

distinct

将数据集中的数据去重。使用分布式处理方式实现,与内存集合使用HashSet去重方式不同。

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(
      List(1, 2, 3, 4, 2, 3, 1), 2
    )
    val distinctRDD = rdd.distinct()
    distinctRDD.collect().foreach(println)

    /**
     * 4
     * 2
     * 1
     * 3
     * */

coalesce

根据数据量缩减分区,用于大数据集过滤后,提高小数据集的执行效率。

当Spark程序中存在过多的小任务时,可以通过coalesce合并分区,减少分区个数,进而减少任务调度成本。

 val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(
      List(1, 2, 3, 4, 5, 6), 3
    )
    // 无shuffle
    val coaRDD = rdd.coalesce(2)
    // 有shuffle
    coaRDD.saveAsTextFile("output1")

TIP:

1、coalesce默认不会将分区数据打乱重新组合,这种情况会导致数据不均衡,出现数据倾斜

2、可以设置第二个参数为true,进行shuffle处理,让数据均衡

3、扩大分区时,可以使用coalesce(,true)或者repartition

sortBy

根据指定规则进行排序,默认升序,设置第二个参数改变排序方式。

默认情况下,不会改变分区个数,但是中间存在shuffle处理。

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(
      List(4, 5, 1, 3, 2, 6), 2
    )
    val sortRDD = rdd.sortBy(num => num)
    sortRDD.saveAsTextFile("output")

 

双Value类型

intersection

两个RDD求交集

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val one: RDD[Int] = sc.parallelize(Array(1, 2, 3, 4, 5))
    val two: RDD[Int] = sc.parallelize(Array(1, 2, 4, 9, 8))
    val value: RDD[Int] = one.intersection(two)
    value.collect().foreach(println)

    /**
     * 1
     * 2
     * 4
     * */

union

两个RDD求并集

只是合并不去重,要想去重可以使用 distinct 算子进行去重

 val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val one: RDD[Int] = sc.parallelize(Array(1, 2, 3, 4, 5))
    val two: RDD[Int] = sc.parallelize(Array(1, 2, 4, 9, 8))
    val value: RDD[Int] = one.union(two)
    value.collect().foreach(x => print(x + " "))

    /**
     *1 2 3 4 5 1 2 4 9 8 
     * */

subtract

两个RDD求差集,

拉链, 对应位置一对一映射,组成(key,value),需要每个对应分区上的数据个数相同

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val one: RDD[Int] = sc.parallelize(Array(1, 2, 3, 4, 5))
    val two: RDD[Int] = sc.parallelize(Array(1, 2, 4, 9, 8))
    val value: RDD[Int] = one.subtract(two)
    value.collect().foreach(x => print(x + " "))

    /**
     * 3 5
     * */

zip

拉链操作,以键值对的形式进行合并。

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd1 = sc.makeRDD(List(1, 2, 3, 4))
    val rdd2 = sc.makeRDD(List(3, 4, 5, 6))
    val newRDD = rdd1.zip(rdd2)
    println(newRDD.collect().mkString(","))

    /**
     * (1,3),(2,4),(3,5),(4,6)
     * */

TIP:

1、intersection,union和subtract要求两个RDD中的数据类型保持一致

2、zip:不要求两个RDD中的数据类型保持一致,但要求分区个数以及对应分区上的数据个数保持一致

K-V类型

partitionBy

将数据按照指定artitioner重新进行分区,默认的分区器是HashPartitioner。

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(List(1, 2, 3, 4), 2)
    val newRDD: RDD[(Int, Int)] = rdd.map((_, 1))
    // partitionBy 根据指定的分区规则对数据进行重分区
    newRDD.partitionBy(new HashPartitioner(2))
      .saveAsTextFile("output")

reduceByKey

将数据按照相同的key对value进行聚合。

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(List(("a", 1), ("a", 2), ("a", 3), ("b", 2)))
    // reduceByKey 相同的Key的数据进行value数据的聚合操作
    // scala 语言中一般的聚合都是两两聚合,spark基于scala开发的,所以它的聚合也是两两聚合的
    // reduceByKey 中如果key的数据只有一个,是不会参与运算的。
    val reduceRDD = rdd.reduceByKey(_ + _)
    reduceRDD.collect().foreach(println)

    /**
     * (a,6)
     * (b,2)
     * */

groupByKey

将数据按照相同的key对value进行分组,形成一个对偶元祖。

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(List(("a", 1), ("a", 2), ("a", 3), ("b", 2)))
    // groupByKey : 将数据源中的数据,相同的key的数据分到一个组中,形成一个对偶元组
    // 元组中的第一个元素就是key,第二个元素就是相同key的value集合
    val groupRDD = rdd.groupByKey()
    groupRDD.collect().foreach(println)

    /**
     * (a,CompactBuffer(1, 2, 3))
     * (b,CompactBuffer(2))
     * */

aggregateByKey

根据不同的规则进行分区内计算和分区间计算。

   val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(List(("a", 1), ("a", 2), ("a", 3), ("a", 4)), 2)
    // 分区内和分区间的计算规则可以不同,也可以相同
    rdd.aggregateByKey(0)(
      (x, y) => math.max(x, y),
      (x, y) => x + y
    ).collect().foreach(println)


    /**
     * (a,6)
     * */

foldByKey

aggregateByKey的简化操作,分区内和分区间的计算规则一样

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(List(("a", 1), ("a", 2), ("a", 3), ("a", 4)), 2)

    // 分区内和分区间的计算规则可以相同
    //   rdd.aggregateByKey(0)(
    //     (x,y) => x + y,
    //     (x,y) => x + y
    //   ).collect().foreach(println)

    // 可以使用foldByKey来简化
    rdd.foldByKey(0)(_ + _).collect().foreach(println)

    /**
     *(a,10)
     * */

combineByKey

针对相同K,将V合并成一个集合。

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(List(("a", 1), ("a", 2), ("b", 3),
      ("b", 4), ("b", 5), ("a", 6)), 2)
    // 获取相同key的数据的平均值 => (a,3) (b,4)
    // combineByKey 需要三个参数
    // 第一个参数表示:将相同key的第一个数据进行数据结构的转换,实现操作
    // 第二个参数表示:分区内的计算规则
    // 第三个参数表示:分区间的计算规则
    val newRDD = rdd.combineByKey(
      v => (v, 1), // 转换为 tuple是在运行当中动态得到的,所以下面的tuple需要添加数据类型
      (t: (Int, Int), v) => {(t._1 + v, t._2 + 1)},
      (t1: (Int, Int), t2: (Int, Int)) => {(t1._1 + t2._1, t1._2 + t2._2)})
    val resultRDD = newRDD.mapValues {
      case (sum, cnt) => sum / cnt
    }
    resultRDD.collect().foreach(println)

    /**
     * (b,4)
     * (a,3)
     * */

join

在类型为(K,V)和(K,W)的RDD上调用,返回一个相同的key对应的所有元素连接在一起的(K,(V,W))的RDD。

val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(List(("a", 1), ("b", 2), ("c", 3), ("d", 4)))
    val rdd2 = sc.makeRDD(List(("a", 5), ("a", 6), ("e", 8), ("c", 7)))
    // join : 两个不同数据源的数据,相同的key的value会连接在一起,形成元组。
    //  如果两个数据源中key没有匹配上,那么数据不会出现在结果中。
    //  如果两个数据源中key有多个相同的,会依次匹配,可能会出现笛卡尔积,数据量会几何性增长,会导致性能降低
    rdd.join(rdd2).collect().foreach(println)

    /** (a,(1,5))
     * (a,(1,6))
     * (c,(3,7)) */

sortByKey

在一个(K,V)的RDD上调用,K必须实现ordered接口,返回一个按照key进行排序的(K,V)的RDD

val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(List(("a", 1), ("b", 2), ("c", 3), ("d", 4)))
    //按照key对rdd中的元素进行排序,默认升序
    rdd.sortByKey().collect().foreach(println)
    //降序
    println("----------")
    rdd.sortByKey(false).collect().foreach(println)

    /**
     * (a,1)
     * (b,2)
     * (c,3)
     * (d,4)
     * ----------
     * (d,4)
     * (c,3)
     * (b,2)
     * (a,1)
     * */

mapValues

针对于(K,V)形式的类型只对V进行操作

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(List(("a", 1), ("b", 2), ("c", 3), ("d", 4)))
    rdd.mapValues("pre_" + _).collect().foreach(println)

    /**
     * (a,pre_1)
     * (b,pre_2)
     * (c,pre_3)
     * (d,pre_4)
     * */

cogroup

相同的key,value分组后连接起来。

    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Operator"))
    val rdd = sc.makeRDD(List(("a", 1), ("b", 2), ("c", 3), ("d", 4)))
    val rdd2 = sc.makeRDD(List(("a", 5), ("a", 6), ("e", 8), ("c", 7)))
    // cogroup : connect + group (分组,连接)
    // 可以有多个参数
    rdd.cogroup(rdd2).collect().foreach(println)

    /** *
     * (a,(CompactBuffer(1),CompactBuffer(5, 6)))
     * (b,(CompactBuffer(2),CompactBuffer()))
     * (c,(CompactBuffer(3),CompactBuffer(7)))
     * (d,(CompactBuffer(4),CompactBuffer()))
     * (e,(CompactBuffer(),CompactBuffer(8)))
     * */

行动算子

行动算子,其实就是触发作业执行的方法
底层代码调用的是环境对象中 runJob 方法,调用dagScheduler的runJob方法创建ActiveJob,并提交执行。

reduce

聚合RDD中的所有数据,先聚合分区内数据,在聚合分区间数据。

    val conf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(conf)
    val rdd = sc.parallelize(List(1, 2, 3, 4, 5))
    val i = rdd.reduce(_ + _)
    println(i)

    /**
     * 15
     * */

 

 

collect

采集,该方法会将不同分区间的数据按照分区顺序采集到Driver端,形成数组。

 val conf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(conf)
    val rdd = sc.parallelize(List(1, 2, 3, 4, 5))
    val ints = rdd.collect()
    ints.foreach(println)

    /**
     * 1
     * 2
     * 3
     * 4
     * 5
     * */

count

统计数据个数。

   val conf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(conf)
    val rdd = sc.parallelize(List(1, 2, 3, 4, 5))
    val l = rdd.count()
    println(l)

    /**
     * 5
     * */

first

获取RDD中的第一个元素。

    val conf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(conf)
    val rdd = sc.parallelize(List(1, 2, 3, 4, 5))
    val i = rdd.first()
    println(i)

    /**
     * 1
     * */

take

获取RDD前n个元素组成的数组。

    val conf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(conf)
    val rdd = sc.parallelize(List(1, 2, 3, 4, 5))
    val ints = rdd.take(2)
    println(ints.mkString(","))

    /**
     * 1,2
     * */

takeOrdered

获取RDD排序后的前n个元素组成的数组

    val conf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(conf)
    val rdd = sc.parallelize(List(1, 2, 3, 4, 5))
    val rdd1 = sc.makeRDD(List(4, 3, 2, 1))
    val ints1 = rdd1.takeOrdered(2)
    println(ints1.mkString(","))

    /**
     * 1,2
     * */

aggregate

将每个分区里面的元素通过分区内逻辑和初始值进行聚合,然后用分区间逻辑和初始值(zeroValue)进行操作。注意:分区间逻辑再次使用初始值和aggregateByKey是有区别的。

fold

折叠操作,aggregate的简化操作,分区内逻辑和分区间逻辑相同。

  val conf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(conf)
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4), 8)
    println(rdd.aggregate(10)(_ + _, _ + _))
    println("-----------")
    //fold 是aggregate的简化版
    println(rdd.fold(10)(_ + _))

    /**
     * 100
     * -----------
     * 100
     * */

countByValue

统计每个value的个数

countByKey

统计每种key的个数。

​
    val conf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(conf)
    val rdd: RDD[(Int, String)] = sc.makeRDD(List((1, "a"), (1, "a"), (1, "a"), (2, "b"), (3, "c"), (3, "c")))
    println(rdd.countByKey())
    val intToLong = rdd.countByValue()
    println(intToLong)

    /**
     * Map(1 -> 3, 2 -> 1, 3 -> 2)
     * Map((3,c) -> 2, (1,a) -> 3, (2,b) -> 1)
     * */

​

foreach

遍历RDD中每一个元素。

    val conf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(conf)
    val value: RDD[Int] = sc.parallelize(Array(1, 2, 3, 4))
    value.collect().foreach(println)

    /**
     * 1
     * 2
     * 3
     * 4
     * */

save

(1)saveAsTextFile(path)保存成Text文件
(2)saveAsSequenceFile(path) 保存成Sequencefile文件
(3)saveAsObjectFile(path) 序列化成对象保存到文件

    val conf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(conf)

    val rdd = sc.makeRDD(List(("a", 1), ("a", 2), ("a", 3), ("b", 4)), 2)
    rdd.saveAsTextFile("output")
    rdd.saveAsObjectFile("output1")
    //    saveAsSequenceFile 方法要求数据的格式必须为 K - V 键值对类型
    rdd.saveAsSequenceFile("output2")

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Java基础】-【SpringMVC】

目录什么是MVC?DAO层是做什么的?Spring MVC的执行流程Spring MVC常用注解Spring MVC的拦截器怎么去做请求拦截?其他cookie和session的区别cookie和session各自适合的场景session的工作原理get请求与post请求的区别get请求的参数能放到body里面…

JAVASE基础(一)

这里写目录标题一、javaSE基础1.jdk文档2.代码量统计工具3.文档注释4.反编译工具5.JDK、JRE、JVM(java虚拟环境)*6.变量命名规则7.变量的作用域8.数据类型9.进制10.反汇编器javap一、javaSE基础 1.jdk文档 Overview (Java Platform SE 8 ) (oracle.com…

stable-diffusion安装和简单测试

参考: https://github.com/CompVis/stable-diffusion 理解DALLE 2, Stable Diffusion和 Midjourney的工作原理 Latent Diffusion Models论文解读 【生成式AI】淺談圖像生成模型 Diffusion Model 原理 【生成式AI】Stable Diffusion、DALL-E、Imagen 背後…

面向对象编程(基础)3:对象的内存解析

目录 3.1 JVM内存结构划分 3.2 对象内存解析 举例: 内存解析图: 面试题:对象名中存储的是什么呢? 3.3 练习 3.1 JVM内存结构划分 HotSpot Java虚拟机的架构图如下。其中我们主要关心的是运行时数据区部分(Runtime …

python字符编码

目录 ❤ 前言 文本编辑器存取文件的原理(nodepad,pycharm,word) python解释器执行py文件的原理 ,例如python test.py 总结 ❤ 什么是字符编码? ASCII MBCS Unicode ❤ 字符编码的发展史 阶段一: 现代计算…

vue - vue中混入mixin的使用

vue中mixin混入的使用1,概念2,使用场景3,开始使用4,局部混入和全局混入5,总结1,概念 官方解释: 混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对…

Python 自动化指南(繁琐工作自动化)第二版:十七、计时、安排任务和启动程序

原文:https://automatetheboringstuff.com/2e/chapter17/ 坐在电脑前运行程序是没问题的,但让程序在没有你直接监督的情况下运行也很有用。您计算机的时钟可以安排程序在某个指定的时间和日期或定期运行代码。例如,你的程序可以每小时抓取一个…

Python 自动化指南(繁琐工作自动化)第二版:十三、使用 EXCEL 电子表格

原文:https://automatetheboringstuff.com/2e/chapter13/ 虽然我们不经常将电子表格视为编程工具,但几乎每个人都使用它们将信息组织成二维数据结构,用公式执行计算,并以图表的形式产生输出。在接下来的两章中,我们将把…

Window10平台下编译Sqlite3.4

1、下载网址:SQLite Download Page 需要下载如下内容: 我这里下载64位的dll 2、我用的vs2019新建一个windows桌面项目,应用程序类型:动态链接库(.dll),空项目: 3、将如下文件复制到工程目录下,然后添加到工程中 添加到…

动力节点老杜Vue笔记——Vue程序初体验

目录 一、Vue程序初体验 前言 1.1 下载并安装vue.js 1.2 第一个Vue程序 1.3 Vue的data配置项 1.4 Vue的template配置项 一、Vue程序初体验 前言 可以先不去了解Vue框架的发展历史、Vue框架有什么特点、Vue是谁开发的,这些对我们编写Vue程序起不到太大的作…

koa开发实践2:为koa项目添加路由模块

nodeJS server-side-developkoa开发实践2:为koa项目添加路由模块上一节:《 koa开发实践2:为koa项目添加路由模块 》| 下一节:《 koa开发实践3:在koa项目中使用 swagger 文档 》作者: 李俊才:…

哪些是真正的全光谱灯品牌呢?推荐五款全光谱护眼灯

所谓全光谱,就是指灯光的色谱成分无限接近太阳光的色谱成分。我们都知道,太阳光不单单只有一束简单的白光,而是有很多种颜色的单色光复合而成,所以它的色彩显色效果非常丰富、真实,这些单色光也成了太阳光的色谱成分。…

浅谈机器学习--聚类

还不了解机器学习?来看! 目录 一.聚类 二.k均值聚类算法(k-means) 1.k均值聚类算法的流程 二.k均值算法的改进 1.二分k-means算法 2.k-means算法 3.k-medoids算法 4.Mini Batch k-means算法 三.DBSCAN算法 1.​编辑-邻域 2.核心点和边界点 …

关于TextureRender适配的解决方案

当我们用摄像机渲染出一个图片,显示在UI的时候,会发现,你如果自适配,那么就会拉伸图片,导致人物或者场景变形。 我最近就遇到了这个事,这里我给出几种问题和解决方案: 1 :当我们想…

NSSCTF Round#11 --- 密码个人赛 wp

文章目录ez_encMyMessageMyGameez_signinez_facez_enc 题目: ABAABBBAABABAABBABABAABBABAAAABBABABABAAABAAABBAABBBBABBABBABBABABABAABBAABBABAAABBAABBBABABABAAAABBAAABABAABABBABBBABBAAABBBAABABAABBAAAABBBAAAABAABBBAABBABABAABABAAAAABBBBABAABBBBAAAAB…

开心档之开发入门网-C++ 变量类型

C 变量类型 目录 C 变量类型 C 中的变量定义 C 中的变量声明 实例 实例 C 中的左值(Lvalues)和右值(Rvalues) 变量其实只不过是程序可操作的存储区的名称。C 中每个变量都有指定的类型,类型决定了变量存储的大小…

Java多线程:线程组

线程组 可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的组织结构有点类似于树的形式,如图所示: 线程组的作用是:可以批量管理线程或线程组对象…

电脑清理怎么做?5个方法帮你解决电脑空间不足的问题!

案例:电脑清理怎么做? 【求一个电脑清理的好方法!电脑垃圾文件太多了又不敢随意删除,怕误删重要的文件!哪位友友可以帮我出出主意呀?到底应该怎么清理电脑呢?】 电脑使用的时间长了都会慢慢变…

(链表)合并两个排序的链表

文章目录前言:问题描述:解题思路:代码实现:总结:前言: 此篇是针对链表的经典练习。 问题描述: 输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节…

用队列实现栈和用栈实现队列

目录用队列实现栈创建栈实现入栈实现出栈判空取栈顶元素释放用栈实现队列创建队列入队出队返回队列开头的元素判空释放前面我们实现了栈和队列,其实栈和队列之间是可以相互实现的 下面我们来看一下 用 队列实现栈 和 用栈实现队列 用队列实现栈 使用两个队列实现一…