10月小结

mapreduce

1、map进行统计:相同的值会统一的放入一组,丢给reduce进行计算

2、reduce进行计算:对map传来的一组值进行累加输出

小结:

Job中的入口不要设置错,是否return job视情况而定

单个job可以直接输出,多个job需要添加线程依赖

没有mainRun方法,需要写完整路径名来访问job。简化:在自己pom文件设置job访问入口

job读取文件的方式有5种,都会输出<k,v>

1)TextInputFormat:默认,按照文件切分,按行读取

2)NLineInputFormat:按设置的行切分,按行读取

3)KeyValueTextInputFormat:按照文件切分,按行读取,主要用于处理数据中具有明显的key-value样式的数据

map数量多少根据文件切分而来

reduce数量的多少可以通过人工setNumReduceTasks设置(默认为1个)。一个reduce任务的输入往往来自于所有 mapper 的输出, reduce 按照 key 对升序进行排序 ,可以重写排序方法 ,进行自定义排序

job里设置多个reduce时,可能会产生数据倾斜的问题,默认用哈希值来setPartitionerClass进行解决,也可以根据实际情况设置分区

读入文件的操作由 hadoop内部完成,我们只需利用FileInputFormat 告知输入/输出的文件目录即可

要事先想好map与reduce的I/O值是什么类型,在Job里设置时也不要出错

map与reduce中间可以setCombinerClass进行计算优化

map与reduce之间有自己的排序方法shuffle,可以继承Comparator类重写它的排序方法,根据key值进行顺/逆序;或是自定义排序类,继承WritableComparator类重写排序规则,在job中setSortComparatorClass设置自己的排序方法

Shuffle的key只起指定reduce 的作用,Shuffle的key产生的机制有 partitioner 负责

建议

1、讲课吐字不清淅,有时候听不清他在说什么。建议练练普通话

2、讲课逻辑混乱,没有第一步、第二步这种一步一步的节奏,有时候突然跳到其他的地方,直接看不懂。建议跟张焱老师后面学学讲课节奏

3、课程安排不合理,Linux基本命令都不会,直接就硬操作虚拟机真的一脸懵逼。衔接的这么混乱,对我们造成的损失是否会有相应的赔偿

4、有时候抽象的知识他不画图,总是指望一张图能解释所有概念,理解起来很费解。建议多画图

5、上课不备课,有时候上课突然卡住卡半节不讲话课,再讲时思路直接断掉。建议给我们上课时备备课,别老翻车

6、讲解代码时不敲代码,直接复制粘贴一大段,我们自己手敲还要理解消化根本跟不上。建议手敲代码,别老复制,边敲的时候边讲解更利于理解消化

7、笔记做的太乱了,没有条理,没有标注,只有他自己能看懂,跟他说了到现在还没改。建议天天都写个课程笔记,方便我们理解

scala与java区别:

mian函数形式上有区别

语句结尾可以不加分号

不需要定义数据类型,Scala自动判断

使用关键词 "var" 声明变量,使用关键词 "val" 声明常量

支持多个变/常量同时声明:val xmax,ymax,mmax,nmax =100

Scala

Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。

Scala 源代码被编译成 Java 字节码,所以它可以运行于 JVM 之上,并可以调用现有的 Java 类库

数组:不可变(可变:ArrayBuffer)
object Test {
   def main(args: Array[String]) {
      var myList = Array(1.9, 2.9, 3.4, 3.5)
     
      // 输出所有数组元素
      for ( x <- myList ) {
         println( x )
      }
​
      // 计算数组所有元素的总和
      var total = 0.0;
      for ( i <- 0 to (myList.length - 1)) {
         total += myList(i);
      }
      println("总和为 " + total);
​
      // 查找数组中的最大元素
      var max = myList(0);
      for ( i <- 1 to (myList.length - 1) ) {
         if (myList(i) > max) max = myList(i);
      }
      println("最大值为 " + max);
      
       // 创建矩阵
      for (i <- 0 to 2) {
         for ( j <- 0 to 2) {
            myMatrix(i)(j) = j;
         }
      }
     
      // 打印二维阵列
      for (i <- 0 to 2) {
         for ( j <- 0 to 2) {
            print(" " + myMatrix(i)(j));
         }
         println();
      }
      
      //合并数组
      var myList1 = Array(1.9, 2.9, 3.4, 3.5)
      var myList2 = Array(8.9, 7.9, 0.4, 1.5)
​
      var myList3 =  concat( myList1, myList2)
     
      // 输出所有数组元素
      for ( x <- myList3 ) {
         println( x )
      }
      
      //区间数组
      var myList1 = range(10, 20, 2)
      var myList2 = range(10,20)
​
      // 输出所有数组元素
      for ( x <- myList1 ) {
         print( " " + x )
      }
      println()
      for ( x <- myList2 ) {
         print( " " + x )
      }
   
   }
}
Scala Collection
1、List(列表):不可变、值一旦被定义了就不能改变,否则地址改变(可变List:ListBuffer)
​
object Test {
   def main(args: Array[String]) {
   
      // 字符串列表
      val site0: List[String] = List("Runoob", "Google", "Baidu")
​
      val site = "Runoob" :: ("Google" :: ("Baidu" :: Nil))
      val nums = Nil
​
      println( "第一网站是 : " + site.head )
      println( "最后一个网站是 : " + site.tail )
      println( "查看列表 site 是否为空 : " + site.isEmpty )
      println( "查看 nums 是否为空 : " + nums.isEmpty )
      
      //连接列表
      val site1 = "Runoob" :: ("Google" :: ("Baidu" :: Nil))
      val site2 = "Facebook" :: ("Taobao" :: Nil)
​
      // 使用 ::: 运算符
      var fruit = site1 ::: site2
      println( "site1 ::: site2 : " + fruit )
     
      // 使用 List.:::() 方法
      fruit = site1.:::(site2)
      println( "site1.:::(site2) : " + fruit )
​
      // 使用 concat 方法
      fruit = List.concat(site1, site2)
      println( "List.concat(site1, site2) : " + fruit  )
      
      //使用 List.fill() 方法来创建一个指定重复数量的元素列表
      val site = List.fill(3)("Runoob") // 重复 Runoob 3次
      println( "site : " + site  )
​
      val num = List.fill(10)(2)         // 重复元素 2, 10 次
      println( "num : " + num  )
      
      //List.reverse 用于将列表的顺序反转
      val site = "Runoob" :: ("Google" :: ("Baidu" :: Nil))
      println( "site 反转前 : " + site )
​
      println( "site 反转后 : " + site.reverse )
   }
}
   
2、Set(集合):分为可变和不可变的
默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包。默认引用 scala.collection.immutable.Set
​
object Test {
   def main(args: Array[String]) {
      val site = Set("Runoob", "Google", "Baidu")
      val nums: Set[Int] = Set()
​
      println( "第一网站是 : " + site.head )
      println( "最后一个网站是 : " + site.tail )
      println( "查看列表 site 是否为空 : " + site.isEmpty )
      println( "查看 nums 是否为空 : " + nums.isEmpty )
      
      //连接集合
      val site1 = Set("Runoob", "Google", "Baidu")
      val site2 = Set("Faceboook", "Taobao")
​
      // ++ 作为运算符使用
      var site = site1 ++ site2
      println( "site1 ++ site2 : " + site )
​
      //  ++ 作为方法使用
      site = site1.++(site2)
      println( "site1.++(site2) : " + site )
      
      // 查找集合中最大与最小元素
      val num = Set(5,6,9,20,30,45)
   
      println( "Set(5,6,9,20,30,45) 集合中的最小元素是 : " + num.min )
      println( "Set(5,6,9,20,30,45) 集合中的最大元素是 : " + num.max )
      
      //使用 Set.& 方法或 Set.intersect 方法来查看两个集合的交集元素
      val num1 = Set(5,6,9,20,30,45)
      val num2 = Set(50,60,9,20,35,55)
​
      // 交集
      println( "num1.&(num2) : " + num1.&(num2) )
      println( "num1.intersect(num2) : " + num1.intersect(num2) )
   }
}
​
3、Map(映射):可变与不可变。默认情况下 Scala 使用不可变 Map。如果你需要使用可变集合,你需要显式的引入 import scala.collection.mutable.Map 类
​
object Test {
   def main(args: Array[String]) {
      val colors = Map("red" -> "#FF0000",
                       "azure" -> "#F0FFFF",
                       "peru" -> "#CD853F")
​
      val nums: Map[Int, Int] = Map()
​
      println( "colors 中的键为 : " + colors.keys )
      println( "colors 中的值为 : " + colors.values )
      println( "检测 colors 是否为空 : " + colors.isEmpty )
      println( "检测 nums 是否为空 : " + nums.isEmpty )
      
      //使用 ++ 运算符或 Map.++() 方法来连接两个 Map,Map 合并时会移除重复的 key
      val colors1 = Map("red" -> "#FF0000",
                        "azure" -> "#F0FFFF",
                        "peru" -> "#CD853F")
      val colors2 = Map("blue" -> "#0033FF",
                        "yellow" -> "#FFFF00",
                        "red" -> "#FF0000")
​
      //  ++ 作为运算符
      var colors = colors1 ++ colors2
      println( "colors1 ++ colors2 : " + colors )
​
      //  ++ 作为方法
      colors = colors1.++(colors2)
      println( "colors1.++(colors2) : " + colors )
      
      //通过 foreach 循环输出 Map 中的 keys 和 values
      val sites = Map("runoob" -> "http://www.runoob.com",
                       "baidu" -> "http://www.baidu.com",
                       "taobao" -> "http://www.taobao.com")
​
      sites.keys.foreach{ i =>  
                           print( "Key = " + i )
                           println(" Value = " + sites(i) )}
   }
}
   
4、元组:不可变,下标从1开始
​
object Test {
   def main(args: Array[String]) {
      val t = (4,3,2,1)
​
      val sum = t._1 + t._2 + t._3 + t._4
​
      println( "元素之和为: "  + sum )
      
      //遍历
      t.productIterator.foreach(println(_))
      t.productIterator.foreach(x => print(x + " "))
      for (x <- t.productIterator) {
            print(x + "|")
        }
      //元素拼接
      println(t.productIterator.mkString("|"))
      
      //使用 Tuple.toString() 方法将元组的所有元素组合成一个字符串
      val t = new Tuple3(1, "hello", Console)
     
      println("连接后的字符串为: " + t.toString() )
      
      //使用 Tuple.swap 方法来交换元组的元素。只有Tuple2生效
      val t = new Tuple2("www.google.com", "www.runoob.com")
     
      println("交换后的元组: " + t.swap )
   }
}

Scala中的类不声明为public,一个Scala源文件中可以有多个类

在scala类中,与类名相同的对象叫做伴生对象,类和伴生对象之间可以相互访问私有的方法和属性

Scala 中没有 static ,但是它也为我们提供了单例模式的实现方法,那就是使用关键字 object

Scala Trait(特征) 相当于 Java 的接口

Scala 模式匹配
match 对应 Java 里的 switch,但是写在选择器表达式之后。即: 选择器 match {备选项}
match 表达式通过以代码编写的先后次序尝试每个模式来完成计算,只要发现有一个匹配的case,剩下的case不会继续匹配。
object Test {
   def main(args: Array[String]) {
      println(matchTest("two"))
      println(matchTest("test"))
      println(matchTest(1))
      println(matchTest(6))
​
   }
   def matchTest(x: Any): Any = x match {
      case 1 => "one"
      case "two" => 2
      case y: Int => "scala.Int"
      case _ => "many"
   }
}
​
//使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配
object Test {
   def main(args: Array[String]) {
        val alice = new Person("Alice", 25)
        val bob = new Person("Bob", 32)
        val charlie = new Person("Charlie", 32)
   
    for (person <- List(alice, bob, charlie)) {
        person match {
            case Person("Alice", 25) => println("Hi Alice!")
            case Person("Bob", 32) => println("Hi Bob!")
            case Person(name, age) =>
               println("Age: " + age + " year, name: " + name + "?")
         }
      }
   }
   // 样例类
   case class Person(name: String, age: Int)
}

jar、瘦包(没有依赖)->shade、胖包(会将所需要的依赖一起打包)->assembly、自定义胖包(可以让输出的结构清晰而标准化,需要自定义配置)

combineByKey

createCombiner: V => C ,生成初始化 值 是区间内要形成的数据形式实例 mergeValue: (C, V) => C,分区内 计算逻辑 mergeCombiners: (C, C) => C, 不同分区间 计算逻辑

.combineByKey( (v:(String,Int) ) => ( mutable.SetString , v.2 ), ( c:(mutable.Set[String], Int) , v: (String,Int) ) => { c.1.add(v.1) val count = c.2 + v.2 (c.1,count) }, (c1: (mutable.Set[String], Int), c2: (mutable.Set[String], Int)) => { c1.1 ++= c2.1 val count = c1.2 + c2.2 (c1._1,count) } )

aggregateByKey:combineByKey进阶版,简化初始值操作

.aggregateByKey((mutable.SetString , 0) )( ( c:(mutable.Set[String], Int) , v: (String,Int) ) => { c.1.add(v.1) val count = c.2 + v.2 (c.1,count) }, (c1: (mutable.Set[String], Int), c2: (mutable.Set[String], Int)) => { c1.1 ++= c2.1 val count = c1.2 + c2.2 (c1.1,count) } )

foldByKey:aggregateByKey 的简化操作,只有seqop 和combop 相同可使用
reduceByKey:分区聚合,常用

reduceByKey与groupByKey区别:reduceByKey多一次预聚合操作

sortBy排序

1)自带sort、自定义sort比较
val a = List("01 hadoop","06 spark", "02 flume","03 hive")
println(a)
 for (elem <- a) {println(elem)}
 a.sorted.reverse.foreach(println)
  println("05 ff".compareTo("06 ee"))
2)先比较第2个,再比较第1个
val a = List((1, "aa"), (2, "aa"), (6, "bb"), (3, "bb"), (86, "gg"), (0, "gg"))
a.sortBy(x => (x._2, x._1))
   .foreach(println)

数据是否发生倾斜:看执行速度是否快,快则无倾斜

数据倾斜解决方案:先对数据加前缀做一次MR,再把前缀去掉做一次MR

  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值