快学Big Data -- Scala总结(二十二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xfg0218/article/details/82381647

Scala总结

凡事豫则立,不豫则废;言前定,则不跲;事前定,则不困。 — 《礼记·中庸》

官网:http://www.scala-lang.org/download/

概述

听说scala是一门神一样的语言,接下来咱们也来了解一下这门神奇的语言。

 

文件类型

  1. 后缀为class的:相当于创建一个类
  2. 后缀为Object的:相当于创建一个对象,或者叫做伴生对象
  3. 后缀为Trait的:相当于接口

环境安装

1-1)、安装JDK

   运行scala需要JDK的环境,所以在安装scala之前需要安装JDK的环境。

1-2)、安装scala

下载:链接:http://pan.baidu.com/s/1nvsB9rF 密码:qy8e 如果无法下载请联系作者。

或者 http://downloads.typesafe.com/scala/2.11.5/scala-2.11.5.tgz

 

[root@hadoop1 local]# tar -zxvf scala-2.10.6.tgz

[root@hadoop1 local]# vi /etc/profile

加入以下配置:

export SCALA_HOME=/usr/local/scala-2.10.6

[root@hadoop1 local]# source  /etc/profile

1-3)、运行

[root@hadoop1 local]# clear

[root@hadoop1 local]# scala

Welcome to Scala version 2.10.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_80).

Type in expressions to have them evaluated.

Type :help for more information.

 

scala> print("wordcount")

wordcount

scala> 100+100

res1: Int = 200

 

scala> print(res1)

200

scala>

 

scala 基础

1-1)、声明变量

// 整形变量

scala> val int=100

int: Int = 100

 

// 字符型变量

scala> val string="wordcount"

string: String = wordcount

 

scala> val string:String="wordcount"

string: String = wordcount

 

// byte的类型

scala> val byte ='a'

byte: Char = a

 

//  char的类型

scala> val char = 'a'

char: Char = a

 

// Short的类型

scala> val short = 10L;

short: Long = 10

 

// Long类型

scala> val long =100L

long: Long = 100

 

// Float类型

scala> val float =10.1

float: Double = 10.1

 

// Boolean类型

scala> val boolean = true

boolean: Boolean = true

 

// double类型

scala> val double = 10.1

double: Double = 10.1

 

 

注意在定义数据类型时:val 的缩写是value 数据是不可改变的,var 是可变长度的,在使用时建议使用val 参数,因为在JVM垃圾回收时会更方便。

1-2)、表达式

  1. 、IF表达式

第一种写法:

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

    val index = 20

    if (index > 10) {

      println("这个数大于10")

    } else {

      println("这个数小于10")

    }

 

}    

 

第二种写法:

val x = 10

    // y直接接受返回的值

    val y = {

      if (x > 10) {

        100

      } else if (x > 10 && x < 1000) {

        1000

      } else {

        "error"

      }

    }

    println(y)

 

 

第三种写法:

 val x = 10

    // y直接接受返回的值

    val y =

      if (x > 10) {

        100

      } else if (x > 10 && x < 1000) {

        1000

      } else {

        "error"

      }

println(y)

 

B)、块表达式

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

val value = if (index == 20) {

      "ok"

    } else {

      "flase"

    }

    print("value:" + value)

}

 

C)、For循环

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

    // Array 的迭代

    var vls = Array("34", "43", "343", "43");

    for (y <- vls) {

      println("y:" + y);

    }

 

    //  可以把两套的循环放到一个for里面,与JAVA的for一样

    for (i <- 1 to 3; y <- 1 to 5) {

      println(i + "-" + y)

    }

 

    // yield :表示对之前的数据进行操作,RDD复杂度取决于前面的数据。

val ind = for (i <- 1 to 10) yield i * 10;

    println(ind);

    

    // 迭代

    val arr = Array(1, 2, 3, 4, 5, 6, 7, 8)

    for (x <- arr) {

      print(x)

    }

     

    //  反转

     for (i <- (0 until arr.length).reverse) {

      print(arr(i))

    }

 

  }

 

 // until 是前闭后开的一个关键字  

 val a = Array("a", "b", "c")

 for (i <- 0 to a.length) println(i)

 println("===================")

 for (i <- 0 until a.length) println(i)

 

1-3)、Scala运算符

Scala支持与JAVA一样的运算符,实例如下:

 

A)、实例一

scala> val a = 1

a: Int = 1

 

scala> val b = 2

b: Int = 2

 

scala> val c = a+(b)

c: Int = 3

 

scala> print(c)

3

 

B)、实例二

scala> val str = "wordcount"

str: String = wordcount

 

scala> print(c+str)

3wordcount

 

 

1-4)、方法和函数

A)、定义方法

object ScalaTest {

 

  def function1() {

    println("方法一")

  }

 

  //  unit 相当于没有返回值,相当于JAVA上的void

  def function2(): Unit = {

    println("定义方法二")

  }

 

  def function3(a: Int, b: Int): String = {

    "定义方法三:" + (a + b)

  }

 

  def function4() = {

    println("定义方法四")

  }

 

  def function5(): Int = {

    10 + 1

  }

 

  def function6(a: Int, b: Int) = {

    val value = a + b

    println(value)

  }

 

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

    function1

    function2

    println(function3(1, 2))

    function4

    println(function5)

    function6(1, 2)

  }

}

 

 

方法体是可以不写的,回自动的推断出来,但是对于递归的方法来说是必须要写的。

 

B)、定义函数

方法一:

object ScalaTest {

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

    val index = (x: Int, y: Int) => x + y

    println(index(1, 2))

    val index1 = (x: Int, y: Int) => {

      x + y

    }

    println(index1(1, 3))

  }

}

方法二:

 // 定义原始数组

val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

 

    // 第一种匿名函数有数据类型的限制

    val res = arr.map((x: Int) => x * 10)

println(res.toBuffer)

 

    // 第二种匿名函数有数据类型的限制并把逻辑放在大括号里面

    val re1 = arr.map((x: Int) => {

      x * 10

    })

println(re1.toBuffer)

 

    // 因为有了数据类型的限制直接使用参数

    val re2 = arr.map(x => x * 10)

println(re2.toBuffer)

 

    // 使用神奇的下划线代表arr中的元素

    val re3 = arr.map(_ * 10)

    println(re3.toBuffer)

 

   // 把函数传到方法里面

    val f1 = (x: Int) => x * 10

    println(arr.map(f1).toBuffer)

 

     // 过滤需要的数据

    val re4 = arr.filter(_ % 2 == 0)

    println("filter:" + re4.toBuffer)

  

方法三:

    // 定义最终的函数

    val fun: Int => Int = { x => x * 10 }

println(fun(5))

 

   // 多个参数的实例

    val f3: (Int, Double) => (Double, Int) = { (x, y) => (y, x) }

    val r = f3(3, 3.0)

println(r)

//在一个数据集中可以直接使用点的形式获取数据

println(r._2)

 

 

可以看出下划线可以代表集合中的元素,方法以及函数。

C)、方法和函数的区别

可以看出在定义方法时用def来定义而函数则用val或var来定义,方法一般有返回值,而函数则没有,Scala是函数式编程,所以在scala中可以把一切转化为函数,起到了至关的重要性。

 

函数实例一:

scala> var f1 = (x: Int, y: Int) => x * y;

f1: (Int, Int) => Int = <function2>

scala> print(f1(1,333))

333

 

函数实例二:

scala> var f2 = (x:Int,y:Int) => { x+ y }

f2: (Int, Int) => Int = <function2>

scala> print(f2(33,5667))

5700

D)、将方法转换成函数(神奇的下划线)

scala> def m1(f2: (Int, Int) => Int): Int = {

     |       f2(2, 6)

     | }

m1: (f2: (Int, Int) => Int)Int

scala> var d1 = m1 _

d1: ((Int, Int) => Int) => Int = <function1>

scala> print(d1)

<function1>

 

E)、函数与方法相互转换

package TestScala

 

object Test {

  // 定义一个方法

  def fff(f: Int => Int): Unit = {

    val r = f(10)

    println(r)

  }

 

  // 定义一个函数

  val f0 = (x: Int) => {

    x * x

  }

 

  // 定义一个方法

  def m0(x: Int): Int = {

    x * 10

  }

 

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

    // 把函数传递到方法里面

    fff(f0)

    // 把方法传入到方法里面

    fff(m0)

    fff(m0 _)

    fff((x: Int) => m0(x))

  }

}

1-5)、集合--映射

A)、Array无泛型使用

1-1)、整数

scala> var  arr1 = Array(1,2,445);

arr1: Array[Int] = Array(1, 2, 445)

 

scala> println(arr1.toBuffer)

ArrayBuffer(1, 2, 445)

 

scala> println(arr1(1));

2

 

1-2)、字符串

scala> val arr3 = Array("hadoop", "storm", "scala")

arr3: Array[String] = Array(hadoop, storm, scala)

 

scala> println(arr3.toBuffer)

ArrayBuffer(hadoop, storm, scala)

 

scala>  println(arr3(2))

scala

1-3)、混合

scala> val arr4 = Array("hadoop", "storm", "scala",1,2)

arr4: Array[Any] = Array(hadoop, storm, scala, 1, 2)

 

scala> print(arr4.toBuffer)

ArrayBuffer(hadoop, storm, scala, 1, 2)

scala> print(arr4(3))

1

B)、Array 泛型使用

scala> import scala.collection.mutable.ArrayBuffer

import scala.collection.mutable.ArrayBuffer

 

scala> val ab = ArrayBuffer[Int](6);

ab: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(6)

 

scala> println(ab.toBuffer)

ArrayBuffer(6)

C)、Array 操作

1-1)、循环

yield关键字将原始的数组进行转换会产生一个新的数组,原始的数组不变

 

 val arrq = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)

 

 val res = for (e <- arrq if e % 2 == 0) yield e * 10

 println(res.toBuffer)

 

 val r = arrq.filter(_ % 2 == 0).map(_ * 10)

 println(r.toBuffer)

 

1-2)、数学运算

val arr = Array(1, 2, 3, 4, 5, 643, 333)

 // 求和

 println(arr.sum)

 // 查找最大值

 println(arr.max)

 // 查找最小值

 println(arr.min)

 // 对数据进行反转

 println(arr.sorted.reverse)

 // 对数据进行正序排序

 println(arr.sorted.toBuffer)

 // 对数据进行倒叙排序

 println(arr.sortWith((x, y) => x > y).toBuffer)

 println(arr.sortWith(_ > _).toBuffer)

 // 对数据进行累加

 println(arr.reduce(_ + _))

 println(arr.reduce((x: Int, y: Int) => { x + y }))

1-3)、Map数组的映射

// 这样可以看做成元组的形式

val map = Map("a" -> 1, "b" -> 2, "c" -> 3)

val map1 = Map(("a", 1), ("b", 2), ("c", 3))

// 以下方式在命令行中可用

map += ("d" -> 4)

map += (("e", 5))

// 获取a的值,返回的是Some

val maybeInt: Option[Int] = map.get("a")

println(maybeInt)

// 获取a的值

println(map("a"))

// 获取元素如果没有数据则显示备注的值

println(map.getOrElse("d", "没有找到"))

// 查看集合的大小

println(map.size)

// 查看是否是实体

println(map.empty)

D)、List 操作

  val li = List(1, 2, 3, 4, 4, 5, 6, 7)

  // 在集合的头部追加元素

  val ints: List[Int] = 8 :: li

  println(ints.toBuffer)

  // 往尾部追加数据

  val list1: List[Int] = li.::(8)

  print(list1)

  // 构建list集合

  val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

  // 对每个元素扩大10倍

  list.map((x: Int) => {

      x * 10

  })

  val map: List[Int] = list.map((x: Int) => x * 10)

  println("map = " + map)

  val map1: List[Int] = list.map(_ * 10)

  println("map1 = " + map1)

  //转化为list

  val toList: List[Int] = list.map((x: Int) => x * 10).toList

  println("toList = " + toList)

  // 对元素分组

  val grouped: Iterator[List[Int]] = list.map((x: Int) => x *   10).grouped(4)

  // 转换数据的格式

  val toList1: List[List[Int]] = grouped.toList

  // 对数据进行压平

  val flatten: List[Int] = toList1.flatten

  println("flatten = " + flatten)

  // 对数据进行先扩大十倍在压平

  val map2: List[List[Int]] = toList1.map(_.map(_ * 10))

  println("map2 = " + map2)

  // 先扩大十倍在压平

  val map3: List[Int] = toList1.flatMap(_.map(_ * 10))

  println("map3 = " + map3)

 

 

  // 初始化list集合

  val list = ListBuffer(1, 2, 2, 3, 3, 4, 545, 6, 4556)

  // 对第一个元素进行重新赋值

  list(0) = 100

  // 查看结果

  println("list = " + list.toBuffer)

  // 在list的后面追加一个元素

  list += 8888

  println(list.toBuffer)

  // 以元组的形式增加数据

  list += (1, 8888, 99999)

  println(list.toBuffer)

  // 在元素的尾部追加数据

  list.append(1234567890)

  println(list.toBuffer)

E)、Set 操作

 // 创建可变的set的集合

 val set = new HashSet[Int]()

 // 为元素赋值

 val ints: HashSet[Int] = set + 1

 println(ints.toBuffer)

 // 增加元素

 val ints1: HashSet[Int] = set ++ Set(1, 2, 3, 4, 5, 6)

 println(ints1.toBuffer)

 val ints2: Set[Int] = Set(7, 8, 9) ++ set

 println(ints2.toBuffer)

 val add: Boolean = set.add(88888888)

 println(add.toString)

// 删除元素

set.remove(2)

  println("set = " + set)

F)、HashMap 操作

 // 创建可变长度的hashMao

 val map = new mutable.HashMap[String, Int]()

 // 增加元素

 map.put("xiaozhang", 1)

 println("map = " + map)

 map("xiaowang") = 2

 map += (("xiaoli", 3))

 println("map = " + map)

G)、集合小结

import scala.Function4

import scala.collection.mutable.HashMap

 

object ScalaTest {

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

    val list0 = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);

    println(list0.toBuffer)

    println(list0.toBuffer.sorted)

    println(list0.toBuffer.sorted.reverse)

    println(list0.toBuffer.sorted.reverse.grouped(4).toList)

    println(list0.toBuffer.sorted.reverse.grouped(4).toList.flatten)

    println(list0.toBuffer.sorted.reverse.grouped(4).toList.flatMap(_.map(_ * 10)));

    println("-------------------------------------")

 

    // heoolword

    val lines = Array("hellow hell", "xiaozhang xiaowang", "xiao zhang", "da xiao budabuxiao", "xiao xiao xiao xiao");

    println(lines.flatMap(_.split(" ")).map((_, 1)).groupBy(_._1).map(t => (t._1, t._2.size)).toList.sortBy(_._2).toList);

    println("-------------------------------------")

 

    // flatMap的使用

    var llss = Array("wd vw d ew v", "ee ede eee fv de s", "sd dss sd sd sf", "ww sdcsw www");

    var sdfg = llss.flatMap(_.split(" "));

    println("sdfg:" + sdfg.toBuffer.grouped(4));

    //    val  sf = sdfg.toBuffer.grouped(4);

    println("grouped:" + llss.toBuffer.sorted);

    println(llss.toBuffer.reverse)

    println("-------------------------------------")

  }

}

 

H)、简单的单词统计

// 构造数据

val lines = List("hello xiaozhao", "hello xiaoxu", "hello xiaownag", "hello xiaozhang")

 // 对数据进行分割并进行压平

 val map: List[String] = lines.flatMap(_.split(" "))

 // 对数据进行统计

 val map1: List[(String, Int)] = map.map((_, 1))

 // 对每个元组进行分组

 val by: Map[String, List[(String, Int)]] = map1.groupBy(_._1)

 // 对数据进行累加

 val stringToInt: Map[String, Int] = by.map(t => (t._1, t._2.size))

 // 对数据进行正序排序

 val by1: List[(String, Int)] = stringToInt.toList.sortBy(_._2)

 // 对数据进行倒叙排序

 val reverse: List[(String, Int)] = by1.reverse

 println("reverse = " + reverse)

1-6)、元组

A)、元组实例一

有提示

 

var value, (s, y, z) = (2, 3, 5)

println(value._1)

 

B)、元组实例二

没有提示

 

val index = (1, 2, 3)

println(index._1)

 

 

val t = (1, 3.14, "Fred")

println(t._2)

 

C)、元组操作

val t = (1, 3.14, "Fred")

val t = (1, 3.14, 67)

    t.productIterator.foreach {

     i => println("Value = " + i)

}

 

 

val t = new Tuple2("www.google.com", "www.runoob.com")

println("反转后的元组: " + t.swap)

 

1-7)、 类、对象、继承、超类

Scala的类与Java、C++的类比起来更简洁,学完之后你会感觉Scala更好玩、、

A)、 类 

 package day2scala

/**

 * 在Scala中,类并不用声明为public。

 * Scala源文件中可以包含多个类,所有这些类都具有公有可见性。

 */

class Persion {

 // 用val修饰的变量是只读属性,有getter但没有setter,(相当与Java中用final修饰的变量)

  var id = "xiaozhang"

  // 用var修饰的变量既有getter又有setter

  var age: Int = 18

  // 类私有字段,只能在类的内部使用

  private var name: String = "xiaowang"

  // 对象私有字段,访问权限更加严格的,Person类的方法只能访问到当前对象的字段

  private[this] val age = "48"

}

 

 

object Persion {

  def main(args: Array[String]) {

    var persion = new Persion

    println(persion.id)

    println(persion.name)

    println(persion.age)

  }

}

 

xiaozhang

xiaowang

18

 

 

 

B)、 伴生类

package day2scala

/**

 * 在Scala中,类并不用声明为public。

 * Scala源文件中可以包含多个类,所有这些类都具有公有可见性。

 */

class Persion {

  // 用val修饰的变量是只读属性,有getter但没有setter,(相当与Java中用final修饰的变量)

  var id = "xiaozhang"

  // 用var修饰的变量既有getter又有setter

  var age: Int = 18

  // 类私有字段,只能在类的内部使用

  private var name: String = "xiaowang"

  // 对象私有字段,访问权限更加严格的,Person类的方法只能访问到当前对象的字段

  private[this] val age = "48"

 

}

/**

 * 与属性的类的名字一样,并在同一个包中

 */

object Persion {

 

  def main(args: Array[String]) {

    var persion = new Persion

    println(persion.id)

    println(persion.name)

    println(persion.age)

  }

 

}

 

C)、 构造器 

注意:主构造器会执行类定义中的所有语句

package day2scala

 

class Student(var name: String, var age: Int, faceValue: Double = 99.9, private var height: Int = 20) {

 

  private[this] var gender: String = null

 

  def show() {

    println(faceValue)

  }

 

  //辅助构造器  def this (参数)

  def this(name: String, age: Int, gender: String) {

    //辅助构造器第一行一定要先调用主构造器

    this(name, age)

    this.gender = gender

  }

 

}

 

 

object Student {

  def main(args: Array[String]) {

    var student = new Student("小王", 18, 85, 180)

    println(student.age + "-" + student.height + "-" + student.name + "-" + student.show)

    student.age = 14;

    student.height = 852;

    student.name = "xiaoli"

    student.show

    println(student.age + "-" + student.height + "-" + student.name + "-" + student.show)

  }

 

}

 

 

object Main {

  def main(args: Array[String]) {

    var student = new Student("小王", 18, 85, 180)

    println(student.age + "-" + student.name + "-" + student.show)

  }

 

}

 

 

注意:访问的范围的问题

Private  / private[this]  、、、、

 

D)、 对象

1-1)、 单例对象

package day2scala

 

class SingletonDemo {

 

  SingletonDemo.sayHi()

 

  sayHi()

 

  var name: String = "xiaozhang"

 

  def sayHi() {

    println("这是第一个类的方法")

  }

}

 

object SingletonDemo {

 

  var name: String = "xiaozhang"

 

  def sayHi() {

    println("这是第二类的方法")

  }

 

  def main(args: Array[String]) {

    // 一下调用的是本类的属性

    var sing = SingletonDemo

    sing.sayHi()

    sing.name

 

    // 调用的是SingletonDemo的属性

    var singSin = new SingletonDemo

    singSin.sayHi()

    singSin.name

  }

 

}

1-2)、 应用程序对象

package day3scala

/**

 *  运行main方法的另外一种方式

 *  

 *  继承 App -->  main 方法

 */

object Dau extends App {

  println("sf")

}

 

 

  /** The main method.

   *  This stores all argument so that they can be retrieved with `args`

   *  and the executes all initialization code segments in the order they were

   *  passed to `delayedInit`

   *  @param args the arguments passed to the main method

   */

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

    this._args = args

    for (proc <- initCode) proc()

    if (util.Properties.propIsSet("scala.time")) {

      val total = currentTime - executionStart

      Console.println("[total " + total + "ms]")

    }

  }

 

E)、 apply方法

 

package day3scala

/**

 * apply方法的使用

 */

object Student {

 

  def apply() = {

    println("这是无惨的apply方法")

  }

 

  def apply(name: String): String = {

    println("这是带一个参数的apply的方法" + name + "")

    // 返回的类型

    name

  }

 

  def apply(name: String, sex: Int) = {

    println("这是既有String又有Int类型的apply的方法")

  }

 

  def main(args: Array[String]) {

    Student("小张")

  }

 

}

 

F)、 继承

在scala中扩展类的方式与咱们老朋友JAVA的实现方式是一样一样的,在scala

中定义接口的关键字是Trait

G)、scala超类的实现

package day3scala

/**

 *   一个类可以多实现但是只能单继承,就像一个小孩的特征像爸爸又像他二叔以及三叔

 */

class classDome {

  def say(name: String) = {

    println("classDome 的:" + name)

  }

}

 

trait ClassDomeTrait {

  def classDomeRraitTest(name: String): String = {

    "ClassDomeTrait已被调用" + name

  }

}

 

 

trait ClassDomeTrait1 {

  def ClassDomeTrait1Test = {

    println("ClassDomeTrait1Test已被调用")

  }

 

}

 

object ClassDomeDay3 extends classDome with ClassDomeTrait with ClassDomeTrait1 {

  def main(args: Array[String]) {

    say("小张")

    var test = classDomeRraitTest("大哥大")

    println(test)

    ClassDomeTrait1Test

  }

}

 

1-8)、 模式匹配

A)、匹配字符串以及元组以及偏函数

 package day2scala.cases

 

import scala.util.Random

 

case class Dome3(name: String, higth: String)

case class Dome4(x: Int, y: Int)

case class Dome5(z: Int)

 

/**

 *   匹配字符串可以借助第三方的类来实现参数的传递与获取,这是JAVA比不了的

 */

object Dome2 {

 

  def main(args: Array[String]) {

 

    val arr = Array(Dome3("333", "43"), Dome4(3, 5), Dome5(5));

    // 主要取值的范围

    arr(Random.nextInt(arr.length)) match {

      case Dome3(name, higth) => {

        println("dome3")

      }

      case Dome4(3, 4) => {

        println("Dome4")

      }

      case Dome5(5) => {

        println("exit")

      }

    }

    

    val map = Map("a" -> 1, "b" -> 2, "c" -> 3)

    val v = map.get("a") match {

      case Some(i) => println("-------------------")

      case None => println("++++++++++++++++++++++++++")

    }

 

    def func2(num: String): Int = num match {

      case "one" => 1

      case "two" => 2

      case _ => -1

    }

 

    println(func2("one"))

 

    // 偏函数

    def func1: PartialFunction[String, Int] = {

      case "one" => {

        println("one case")

        1

      }

      case "two" => 2

      case _ => -1

    }

    println(func1("one"))

 

  }

 

}

 

 

B)、类型匹配

 

package day2scala.cases

 

import scala.util.Random

 

case class Dome(name: String)

/**

 *  字符串匹配加类型匹配

 */

object Dome1 {

 

  def main(args: Array[String]) {

    val arr = Array("校长", "小王", "小李", "大和大", "回复", 3, 343.6, 'd', true)

    val name = arr(Random.nextInt(arr.length))

    println(name)

 

    name match {

      case "校长" => println("")

      case "xiaowang" => {

        println("xiaozhang")

      }

      case "小李" => {

        println("小李")

      }

      case x: Int if (x > 10) => {

        println("Int:" + x)

      }

      case y: Double => {

        println("double:" + y)

      }

      case xx: Int if (xx > 20) => {

        throw new Exception("你输入的数大于了20")

      }

      case ("小_", "", "") => {

        println("小_")

      }

      case (_, _, "小_") => {

        println("________小")

      }

      // _ 如果没有匹配则会执行这段代码

      case _ => {

        println("exit")

        exit

      }

    }

 

  }

 

}

 

C)、集合匹配 

package day2scala.cases

/**

 * 集合的匹配

 */

object DomeTest {

  def main(args: Array[String]) {

    val arr = Array(1, 1, 7, 0)

    arr match {

      case Array(1, 1, x, y) => println(x + ":" + y)

      //    case Array(1, 1, 7, y) => println("only 0")

      case Array(0, _*) => println("0 ...")

      case _ => println("something else")

    }

 

    val lst = List(0)

    lst match {

      case 0 :: Nil => println("only 0")

      case x :: y :: Nil => println("x $x y $y")

      case 0 :: a => println("0 ... $a")

      case _ => println("something else")

    }

 

  }

}

 

D)、option 匹配

package day3scala

/**

 * 在scala中option中表示类型可能存在或者可能不存在的值,如果存在则用some表示,没有则用None表示

 */

object OptionDome {

  def main(args: Array[String]) {

    var arr = Map("xiaozhang" -> 2, "xiaowang" -> 4)

    var ls = arr.get("xiaozhang") match {

      case Some(i) => {

        println(i)

      }

      case None => {

        println("没有找到")

      }

    }

 

    // 更好的实现方式

    var ld = arr.getOrElse("c", 0)

    println(ld)

  }

}

E)、偏函数

被花括号括起来的但是没有match的一组叫做偏函数

 

 def func1: PartialFunction[String, Int] = {

      case "one" => {

        println("one case")

        1

      }

      case "two" => 2

      case _ => -1

    }

println(func1("one"))

 

Scala 在win下编译scala文件

1-1)、准备数据

object TestCount {

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

    System.out.print("hellword Scala")

  }

}

1-2)、进行编译并查看结果

 

 

 

IDEA开发Scala程序

1-1)、准备IDEA并安装scala插件

 

 

1-2)、创建scala项目

 

 

 

 

 

1-3)、把项目导出来运行

 

 

 

 

1-4)、运行查看效果

 

Scala 的Actor 编程(也就是Akka的编程)

!   发送异步消息,没有返回值。

!?  发送同步消息,等待返回值。

!!  发送异步消息,有返回值

 

 

react方式会复用线程,比receive更高效

 

实例一:

 

package day2scala.actor

 

import scala.actors.Actor

/**

 *  MyActorTest执行的时候首先调用start方法

 */

object MyActorTest extends Actor {

 

  def act() {

    for (i <- 1 to 10) {

      println("MyActorTest:" + Thread.currentThread().getName())

      Thread.sleep(1000)

    }

  }

}

 

object MyActorTest1 extends Actor {

  def act() {

    for (i <- 1 to 10) {

      println("MyActorTest1:" + Thread.currentThread().getName())

      Thread.sleep(1000)

    }

  }

}

 

object MyActorTest2 {

  def main(args: Array[String]) {

    MyActorTest.start

    MyActorTest1.start

  }

}

 

实例二:

package day2scala.actor

 

import scala.actors.Actor

/**

 * loop 是个无限循环的,相当于oracle上的loop

 */

class YourActorText extends Actor {

 

  def act() {

    loop {

      react {

        case "start" => {

          println("staring .......")

          println(Thread.currentThread().getName())

        }

        case "end" => {

          println("end ......")

          println(Thread.currentThread().getName())

        }

        case "exit" => {

          exit()

        }

      }

    }

  }

}

 

object YourActorText1 {

  def main(args: Array[String]) {

    var your = new YourActorText

    your.start

    your.!("start")

    your.!!("exit")

  }

 

}

 

 

实例三:

package day2scala.actor

 

import scala.actors.Actor

import scala.io.Source

import scala.actors.Future

import scala.collection.mutable.HashSet

import scala.collection.mutable.ListBuffer

 

case class SubmitTask(filePath: String)

case class ResultTask(result: Map[String, Int])

case object StopTask

 

/**

 * loop 是无限循环

 * react 比receive快

 */

class Task extends Actor {

 

  def act() {

    loop {

      react {

        case SubmitTask(filePath) => {

          val result = Source.fromFile(filePath).getLines.toList.flatMap(_.split(" ")).map((_, 1)).groupBy(_._1).mapValues(_.size)

          sender ! ResultTask(result)

        }

        case StopTask => {

          exit()

        }

      }

    }

  }

}

 

object ActorWordCount {

 

  def main(args: Array[String]) {

    val replySet = new HashSet[Future[Any]]()

    val resultList = new ListBuffer[ResultTask]()

    val list = Array[String]("D:\\text.txt", "D:\\text1.txt", "D:\\text2.txt")

    for (filePath <- list) {

      val task = new Task

      val reply = task.start !! SubmitTask(filePath)

      replySet += reply

    }

 

    while (replySet.size > 0) {

      // _.isSet 判断是不是Set集合

      val toCompute = replySet.filter(_.isSet)

      for (f <- toCompute) {

        // 把执行的结果付给ResultTask

        val result = f().asInstanceOf[ResultTask]

        resultList += result

        replySet -= f

      }

      Thread.sleep(1000)

    }

 

    val fr = resultList.flatMap(_.result).groupBy(_._1).mapValues(_.foldLeft(0)(_ + _._2))

    println(fr)

    exit

  }

}

 

 

Scala 高级特性

1-1 )、函数的总结

 

package day3scala

/**

 *  柯里化的函数感觉挺有意思的

 */

object Function {

  def main(args: Array[String]) {

    val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)

    // 定义一个函数并把函数复制给了fun1

    val fun1 = (x: Int) => x * 10

    // 把函数作为参数传入到MAP中

    arr.map(fun1)

    // 匿名函数,直接把结果传入到map中,效果与以前的一样

    arr.map((x: Int) => x * 10)

    // 使用scala的推断类型的方式来进行计算

    arr.map(x => x * 10)

    // 神奇的下划线

    arr.map(_ * 10)

 

    // 定义一个方法

    def m(x: Int) = x * 10

    // 把方法转化为了函数

    val mm = m _

    // 讲方法传入到map中

    arr.map(mm)

 

    for (x <- arr) {

      println(x)

    }

 

    // 柯里化的转换

    def ss(x: Int) = (yy: Int) => x * yy

    // 转化为函数,传递第一个参数

    val ff = ss(4)

    // 传递第二个参数

    val asd = ff(9)

    // 或者这样写

    val dfg = ss(3)(8)

    println(dfg)

 

  }

}

1-2)、隐式转换

A)、查看系统隐式的方法

scala> :implicit -v

/* 78 implicit members imported from scala.Predef */

  /* 48 inherited from scala.Predef */

  implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A]

  implicit def any2Ensuring[A](x: A): Ensuring[A]

  implicit def any2stringadd(x: Any): runtime.StringAdd

  implicit def any2stringfmt(x: Any): runtime.StringFormat

  implicit def boolean2BooleanConflict(x: Boolean): Object

  implicit def byte2ByteConflict(x: Byte): Object

  implicit def char2CharacterConflict(x: Char): Object

  implicit def double2DoubleConflict(x: Double): Object

  implicit def float2FloatConflict(x: Float): Object

  implicit def int2IntegerConflict(x: Int): Object

  implicit def long2LongConflict(x: Long): Object

  implicit def short2ShortConflict(x: Short): Object

 

  implicit def booleanArrayOps(xs: Array[Boolean]): mutable.ArrayOps[Boolean]

  implicit def byteArrayOps(xs: Array[Byte]): mutable.ArrayOps[Byte]

  implicit def charArrayOps(xs: Array[Char]): mutable.ArrayOps[Char]

  implicit def doubleArrayOps(xs: Array[Double]): mutable.ArrayOps[Double]

  implicit def floatArrayOps(xs: Array[Float]): mutable.ArrayOps[Float]

  implicit def genericArrayOps[T](xs: Array[T]): mutable.ArrayOps[T]

  implicit def intArrayOps(xs: Array[Int]): mutable.ArrayOps[Int]

  implicit def longArrayOps(xs: Array[Long]): mutable.ArrayOps[Long]

  implicit def refArrayOps[T <: AnyRef](xs: Array[T]): mutable.ArrayOps[T]

  implicit def shortArrayOps(xs: Array[Short]): mutable.ArrayOps[Short]

  implicit def unitArrayOps(xs: Array[Unit]): mutable.ArrayOps[Unit]

 

  implicit def Boolean2boolean(x: Boolean): Boolean

  implicit def Byte2byte(x: Byte): Byte

  implicit def Character2char(x: Character): Char

  implicit def Double2double(x: Double): Double

  implicit def Float2float(x: Float): Float

  implicit def Integer2int(x: Integer): Int

  implicit def Long2long(x: Long): Long

  implicit def Short2short(x: Short): Short

  implicit val StringCanBuildFrom: generic.CanBuildFrom[String,Char,String]

  implicit def arrayToCharSequence(xs: Array[Char]): CharSequence

  implicit def augmentString(x: String): immutable.StringOps

  implicit def boolean2Boolean(x: Boolean): Boolean

  implicit def byte2Byte(x: Byte): Byte

  implicit def char2Character(x: Char): Character

  implicit def conforms[A]: <:<[A,A]

  implicit def double2Double(x: Double): Double

  implicit def exceptionWrapper(exc: Throwable): runtime.RichException

  implicit def float2Float(x: Float): Float

  implicit def int2Integer(x: Int): Integer

  implicit def long2Long(x: Long): Long

  implicit def seqToCharSequence(xs: IndexedSeq[Char]): CharSequence

  implicit def short2Short(x: Short): Short

  implicit def tuple2ToZippedOps[T1, T2](x: (T1, T2)): runtime.Tuple2Zipped.Ops[T1,T2]

  implicit def tuple3ToZippedOps[T1, T2, T3](x: (T1, T2, T3)): runtime.Tuple3Zipped.Ops[T1,T2,T3]

  implicit def unaugmentString(x: immutable.StringOps): String

 

  /* 30 inherited from scala.LowPriorityImplicits */

  implicit def genericWrapArray[T](xs: Array[T]): mutable.WrappedArray[T]

  implicit def wrapBooleanArray(xs: Array[Boolean]): mutable.WrappedArray[Boolean]

  implicit def wrapByteArray(xs: Array[Byte]): mutable.WrappedArray[Byte]

  implicit def wrapCharArray(xs: Array[Char]): mutable.WrappedArray[Char]

  implicit def wrapDoubleArray(xs: Array[Double]): mutable.WrappedArray[Double]

  implicit def wrapFloatArray(xs: Array[Float]): mutable.WrappedArray[Float]

  implicit def wrapIntArray(xs: Array[Int]): mutable.WrappedArray[Int]

  implicit def wrapLongArray(xs: Array[Long]): mutable.WrappedArray[Long]

  implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): mutable.WrappedArray[T]

  implicit def wrapShortArray(xs: Array[Short]): mutable.WrappedArray[Short]

  implicit def wrapUnitArray(xs: Array[Unit]): mutable.WrappedArray[Unit]

 

  implicit def Boolean2booleanNullConflict(x: Null): Boolean

  implicit def Byte2byteNullConflict(x: Null): Byte

  implicit def Character2charNullConflict(x: Null): Char

  implicit def Double2doubleNullConflict(x: Null): Double

  implicit def Float2floatNullConflict(x: Null): Float

  implicit def Integer2intNullConflict(x: Null): Int

  implicit def Long2longNullConflict(x: Null): Long

  implicit def Short2shortNullConflict(x: Null): Short

  implicit def booleanWrapper(x: Boolean): runtime.RichBoolean

  implicit def byteWrapper(x: Byte): runtime.RichByte

  implicit def charWrapper(c: Char): runtime.RichChar

  implicit def doubleWrapper(x: Double): runtime.RichDouble

  implicit def fallbackStringCanBuildFrom[T]: generic.CanBuildFrom[String,T,immutable.IndexedSeq[T]]

  implicit def floatWrapper(x: Float): runtime.RichFloat

  implicit def intWrapper(x: Int): runtime.RichInt

  implicit def longWrapper(x: Long): runtime.RichLong

  implicit def shortWrapper(x: Short): runtime.RichShort

  implicit def unwrapString(ws: immutable.WrappedString): String

  implicit def wrapString(s: String): immutable.WrappedString

 

 

 

 

 

B)、查看scala.Predef下的隐式的方法

object Predef extends LowPriorityImplicits

 

多看一下Predef类下面的方法,可以看出导入了基本的数据类型以及集合类型

 

C)、查看LowPriorityImplicits类下的隐式方法

 

class LowPriorityImplicits {

  @inline implicit def byteWrapper(x: Byte) = new runtime.RichByte(x)

  @inline implicit def shortWrapper(x: Short) = new runtime.RichShort(x)

  @inline implicit def intWrapper(x: Int) = new runtime.RichInt(x)

  @inline implicit def charWrapper(c: Char) = new runtime.RichChar(c)

  @inline implicit def longWrapper(x: Long) = new runtime.RichLong(x)

  @inline implicit def floatWrapper(x: Float) = new runtime.RichFloat(x)

  @inline implicit def doubleWrapper(x: Double) = new  runtime.RichDouble(x)

  @inline implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x)

}

 

可以看出导入了许多隐式的方法,其中intWrapper方法就是实现了to方法的实现

D)、代码实现

package Rich

 

import java.io.File

 

/**

 * Created by Administrator on 2016/12/3.

 */

object MyPreDef {

  // 定义隐式转换方法(将原来的类型转换为增强的类型)

  implicit def file2RichFile(file: File) = new RichFile(file)

}

 

 

 

 

 

package Rich

import java.io.File

import scala.io.Source

class RichFile(file: File) {

  def read: String = Source.fromFile(file).mkString

}

 

object RichFile {

  def main(args: Array[String]) {

    val file = new File("D:\\china.txt")

    // 装饰模式显示的增强

    val rf = new RichFile(file)

    val read: String = rf.read

    println("read = " + read)

 

    // 隐式增强的方式

    val file1 = new File("D:\\china.txt")

    import MyPreDef.file2RichFile

    val read1: String = file1.read

    println("read1 = " + read1)

 

  }

}

1-3)、柯里化

// 初始化隐士参数

object MyPreDef {

  implicit val aaaa: Int = 1024

}

 

object CurryingTest {

  // 定义一个普通方法

  def curry(x: Int, y: Int) = {

    x * y

  }

 

  // 定义柯里化方法一

  def currying(x: Int)(y: Int) = {

    x * y

  }

 

  // 初始化隐实值

  def curryingImp(x: Int)(implicit y: Int = 100) = {

    x * y

  }

 

  // 定义柯里化方法二

  def curryingTest(x: Int) = (y: Int) => {

    x * y

  }

 

  def main(args: Array[String]) {

    // 调用普通方法

    val curry1: Int = curry(2, 3)

    println("curry1 = " + curry1)

 

    // 调用柯里化的方法

    val currying1: Int = currying(2)(6)

    println("currying1 = " + currying1)

 

    // 把柯里化的方法转换为函数

    val intToInt: (Int) => Int = currying(2) _

    // 调用转换的方法

    val int: Int = intToInt(8)

    println("int = " + int)

 

    // 带有隐士参数的柯里化方法

    val curryingImp1: Int = curryingImp(2)

    println("curryingImp1 = " + curryingImp1)

 

    // 去MyPreDef查找类型匹配的参数,使用最新的参数,如果找不到则使用默认的

    import MyPreDef.aaaa

    val imp: Int = curryingImp(2)

    println("imp = " + imp)

 

    // 测试柯里化方法二

    val test: (Int) => Int = curryingTest(2)

    val test1: Int = test(5)

    println("test1 = " + test1)

  }

}

 

1-4)、泛型

[ T < :    UpperBound ]     上界

[ T >:    LowerBound]        下界

[ T <%   ViewBound]         视图界定

[ T :     ContextBound]       上下界

[ T + ]     斜变

[ -T ]      逆变

 

 

  1. 、上界实例

实体类

package gen

 

class Boy(val name: String, val faceValue: Int) extends Comparable[Boy] {

  // 添加匹配规则

  override def compareTo(o: Boy): Int = {

    this.faceValue - o.faceValue

  }

}

具体实现的类

package gen

 

// 在类中定义泛型

class MrRight[T <: Comparable[T]] {

  // 第二种方式定义泛型

  //  def choose[T <: Comparable[T]](first: T, second: T): T = {

  //    if (first.compareTo(second) > 0) first else second

  //  }

 

  def choose(first: T, second: T): T = {

    if (first.compareTo(second) > 0) first else second

  }

}

 

object MrRight {

  def main(args: Array[String]) {

    val mr = new MrRight[Boy]

    val boy = new Boy("xiaozhang", 88)

    val boy1 = new Boy("xiaowang", 8888)

    val choose: Boy = mr.choose(boy, boy1)

    println("choose = " + choose.name)

  }

}

 

B)、视图界定实例

实体类

package gen

 

// 定义实体类

class Girl(val name: String, val faceValue: Int) {

 

}

 

定义隐式方法

package gen

 

// 定义匹配的规则

object MyPreDef {

  // 隐式的方法

  implicit def girl2Ordered(g: Girl) = new Ordered[Girl] {

    override def compare(that: Girl): Int = {

      g.faceValue - that.faceValue

    }

  }

}

 

具体实现的类

package gen

 

// 实现Ordered方法,Ordered重写了比较条件的方法

class MissRight[T <% Ordered[T]] {

  def choose(first: T, second: T): T = {

    if (first > second) first else second

  }

}

 

object MissRight {

  def main(args: Array[String]) {

    // 导入规则

    import MyPreDef.girl2Ordered

    val mr = new MissRight[Girl]

    // 实例化对象信息

    val g1 = new Girl("xiaolili", 88)

    val g2 = new Girl("xiaomoli", 99)

    // 调用方法调用

    val choose: Girl = mr.choose(g1, g2)

    println("choose = " + choose.name)

  }

}

 

 

视图转换可以把比较规则与实体分离开来,这样就大大的解决了不同的功能的问题。

 

 

C)、上下文界定

实体类

package gen

 

// 定义实体类

class Girl(val name: String, val faceValue: Int) {

 

}

 

定义隐式方法

package gen

 

// 定义匹配的规则

object MyPreDef {

 

  // 上下文转换的值

  implicit object girl2Ordering extends Ordering[Girl] {

    override def compare(x: Girl, y: Girl): Int = {

      x.faceValue - y.faceValue

    }

  }

 

}

 

具体实现的类

package gen

 

// 上下文的界定不需要Ordering不需要指定泛型

class MissRight[T: Ordering] {

  def select(first: T, second: T): T = {

    val ord = implicitly[Ordering[T]]

    if (ord.gt(first, second)) first else second

  }

}

 

object MissRight {

  def main(args: Array[String]) {

    // 导入规则

    import MyPreDef.girl2Ordering

    val mr = new MissRight[Girl]

    // 实例化对象信息

    val g1 = new Girl("xiaolili", 88)

    val g2 = new Girl("xiaomoli", 99)

    // 调用方法调用

    val choose: Girl = mr.select(g1, g2)

    println("choose = " + choose.name)

  }

}

 

Spark-shell 执行Helloword

1-1)、查看启动过程日志信息

[root@hadoop1 bin]# /usr/local/spark-1.3.1-bin-hadoop2.6/bin

[root@hadoop1 bin]# ./spark-shell

16/09/17 23:54:07 INFO DiskBlockManager: Created local directory at /tmp/spark-3f925acf-98d5-43de-b04a-bea37b20bf2d/blockmgr-99460b06-2031-4ac6-b7fd-be2115b3402b

16/09/17 23:54:07 INFO HttpFileServer: HTTP File server directory is /tmp/spark-124e87a9-8e9b-4b90-9627-95ff8dfe67d0/httpd-6390a167-dd6a-49b7-8e95-1b0718dd860c

 

16/09/17 23:54:08 INFO SparkUI: Started SparkUI at http://hadoop1:4040

 

1-2)、查看成成的文件信息:

[root@hadoop1 /]# cd tmp/

spark-3f925acf-98d5-43de-b04a-bea37b20bf2d/blockmgr-99460b06-2031-4ac6-b7fd-be2115b3402b

spark-124e87a9-8e9b-4b90-9627-95ff8dfe67d0/httpd-6390a167-dd6a-49b7-8e95-1b0718dd860c

 

1-3)、计算wordCount

scala> sc.textFile("/usr/local/words.txt")

res0: org.apache.spark.rdd.RDD[String] = /usr/local/words.txt MapPartitionsRDD[1] at textFile at <console>:22

 

scala> sc.textFile("/usr/local/words.txt").flatMap(_.split(" "))

res2: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[4] at flatMap at <console>:22

 

scala> sc.textFile("/usr/local/words.txt").flatMap(_.split(" ")).map((_,1))

res3: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[8] at map at <console>:22

 

scala> sc.textFile("/usr/local/words.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_)

res5: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[17] at reduceByKey at <console>:22

 

scala> sc.textFile("/usr/local/words.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).collect

res6: Array[(String, Int)] = Array((dageda,1), (xiaoli,1), (hellow,4), (xisdsd,1), (xiaozhang,1))

 

1-4)、查看spark默认的指定的分区数

A)、指定分区数

scala> sc.parallelize(1 to 10, 2)

res1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:22

 

scala> res1.partitions.size

res3: Int = 2

B)、没有指定分区数

scala> sc.parallelize(1 to 10)

res4: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[1] at parallelize at <console>:22

 

scala> res4.partitions.size

res5: Int = 1

 

系统根据CPU的核数来分配分区的数量

Wordcount  实例

package day2scala.actor

 

import scala.actors.Actor

import scala.io.Source

import scala.actors.Future

import scala.collection.mutable.HashSet

import scala.collection.mutable.ListBuffer

 

case class SubmitTask(filePath: String)

case class ResultTask(result: Map[String, Int])

case object StopTask

 

/**

 * loop 是无限循环

 * react 比receive快

 */

class Task extends Actor {

 

  def act() {

    loop {

      react {

        case SubmitTask(filePath) => {

          val result = Source.fromFile(filePath).getLines.toList.flatMap(_.split(" ")).map((_, 1)).groupBy(_._1).mapValues(_.size)

          sender ! ResultTask(result)

        }

        case StopTask => {

          exit()

        }

      }

    }

  }

}

 

object ActorWordCount {

 

  def main(args: Array[String]) {

    val replySet = new HashSet[Future[Any]]()

    val resultList = new ListBuffer[ResultTask]()

    val list = Array[String]("D:\\text.txt", "D:\\text1.txt", "D:\\text2.txt")

    for (filePath <- list) {

      val task = new Task

      val reply = task.start !! SubmitTask(filePath)

      replySet += reply

    }

 

    while (replySet.size > 0) {

      // _.isSet 判断是不是Set集合

      val toCompute = replySet.filter(_.isSet)

      for (f <- toCompute) {

        // 把执行的结果付给ResultTask

        val result = f().asInstanceOf[ResultTask]

        resultList += result

        replySet -= f

      }

      Thread.sleep(1000)

    }

 

    val fr = resultList.flatMap(_.result).groupBy(_._1).mapValues(_.foldLeft(0)(_ + _._2))

    println(fr)

    exit

  }

}

 

 

 

Scala 简单RPC实现

1-1)、图解

1-2)、初步实现

A)、服务器端

 import akka.actor.{Actor, ActorRef, ActorSystem, Props}

import com.typesafe.config.ConfigFactory

 

 

class Master extends Actor {

  override def receive: Receive = {

    // Master 发送的消息

    case "hello" => {

      println("hello")

    }

    case "start" => {

      println("start ....")

    }

    case "stop" => {

      println("stop ....")

    }

 

    // 接受客户端的信息

    case "connect" => {

      println("a client connect .....")

      // 发送给Woker发送消息

      sender ! "success"

    }

  }

}

 

object Master {

  def main(args: Array[String]) {

    // Master 的host

    //    val host = args(0)

    val host = "127.0.0.1"

    // Master的port

    //    val port = args(1)

    val port = 8888

    // 拼接字符串

    val confStr =

      s"""

         |akka.actor.provider = "akka.remote.RemoteActorRefProvider"

         |         |akka.remote.netty.tcp.hostname = "$host"

         |         |akka.remote.netty.tcp.port = "$port"

       """.stripMargin

    val conf = ConfigFactory.parseString(confStr)

    // 创建ActorSystem,是单利的,监听Actor的运行情况

    val actorSystem = ActorSystem("MasterActorSystem", conf)

    // 通过actorSystem来创建actor,通过以下两种方式创建

    val master: ActorRef = actorSystem.actorOf(Props[Master], "Master")

    //    val master: ActorRef = actorSystem.actorOf(Props(Master.getClass), "Master")

    // 发送消息

    //    !   发送消息异步消息,没有返回值。

    //    !?  发送同步消息,等待返回值。

    //    !!1  发送异步消息,有返回值

    master ! "hello"

    master ! "start"

    master ! "stop"

    // 等待线程推出的信息

    actorSystem.awaitTermination()

 

  }

}

B)、客户端

import akka.actor.{ Actor, ActorRef, ActorSelection, ActorSystem, Props }

import com.typesafe.config.ConfigFactory

 

/**

 * Created by Administrator on 2016/12/1.

 */

class Worker extends Actor {

 

  // preStart 是在构造器之后,receive之前执行

  override def preStart(): Unit = {

    // 首先和Master 建立链接,拿到Master的引用,并发送下消息

    val selection: ActorSelection = context.actorSelection("akka.tcp://[email protected]:2552/user/Master")

    selection ! "connect"

  }

 

  // 伴生对象的Receive方法

  override def receive: Receive = {

    // Woker 发送消息的匹配

    case "hello" => {

      println("hello")

    }

    case "start" => {

      println("start ....")

    }

    case "stop" => {

      println("stop ....")

    }

    // 接受Master发送的消息

    case "success" => {

      println("a msg for master : success")

    }

  }

}

 

object Worker {

  def main(args: Array[String]) {

    // woker的IP

    val host = "127.0.0.1"

    // woker的端口

    val port = 8888

    // 拼装字符串

    val confStr =

      s"""

         |akka.actor.provider = "akka.remote.RemoteActorRefProvider"

         |akka.remote.netty.tcp.hostname = "$host"

         |akka.remote.netty.tcp.port = "$port"

       """.stripMargin

    // 创建配置工厂

    val conf = ConfigFactory.parseString(confStr)

    // 创建actor的系统配置

    val actorSystem = ActorSystem("WokerActor", conf)

    // 设置actor

    val actorWoker: ActorRef = actorSystem.actorOf(Props[Worker], "Woker")

    actorWoker ! "hello"

    actorWoker ! "start"

    actorWoker ! "stop"

    // 优雅的退出程序

    actorSystem.awaitTermination()

  }

}

1 - 3)、深入探究

A)、服务器端

 

package test.cn.****.test

 

import akka.actor.Actor

import com.typesafe.config.impl.ConfigString

import com.typesafe.config.ConfigFactory

import akka.actor.ActorSystem

import akka.actor.Props

import scala.collection.mutable

import java.util.UUID

import scala.concurrent.duration._

import scala.collection.mutable.HashMap

import scala.collection.mutable.HashSet

 

class TestMaster(val host: String, val port: Int) extends Actor {

  // 保存wokerId 到TestwokerInfo的映射

  val idtoWoker = new HashMap[String, TestWorkerInfo]()

  // 保存所有TestWokerInfo的信息

  val wokers = new HashSet[TestWorkerInfo]

 

  // 单位秒

  val CHECK_INTERVAL = 15000

 

  // 在Receive运行之前运行

  override def preStart(): Unit = {

    import context.dispatcher

    context.system.scheduler.schedule(0 millis, CHECK_INTERVAL millis, self, TestCheckTimeOutWorker)

  }

 

  def receive: Receive = {

    // 接受woker发送过来的注册信息

    case TestRegisterWorker(wokerId, cores, memory) => {

      if (!idtoWoker.contains(wokerId)) {

        try {

          val wokerInfo = new TestWorkerInfo(wokerId, cores, memory)

          idtoWoker(wokerId) = wokerInfo

          wokers += wokerInfo

          sender ! TestRegisterdWorker(s"akka.tcp://${TestMaster.MASTER_SYSTEM}@$host:$port/user/${TestMaster.MASTER_NAME}")

        } catch {

          case t: Throwable => t.printStackTrace()

        }

      }

    }

 

    // worker 发送给master的心跳信息

    case TestHeartbeat(workerId) => {

      if (idtoWoker.contains(workerId)) {

        val workerInfo = idtoWoker(workerId)

        val currentTime = System.currentTimeMillis()

        workerInfo.lastHeartbeatTime = currentTime

      }

    }

 

    case TestCheckTimeOutWorker => {

      val currentTime = System.currentTimeMillis()

      val deadWorkers = wokers.filter { x => currentTime - x.lastHeartbeatTime > CHECK_INTERVAL }

      deadWorkers.foreach {

        x =>

          idtoWoker -= x.wokerId

          wokers -= x

      }

      println("现在存活的个数为:" + wokers.size)

    }

  }

}

 

object TestMaster {

  // 定义常量

  val MASTER_NAME = "TestMaster"

  val MASTER_SYSTEM = "TestMasterActorSystem"

 

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

    val host = "127.0.0.1"

    val port = 8888

 

    val confStr = s"""

         |akka.actor.provider = "akka.remote.RemoteActorRefProvider"

         |akka.remote.netty.tcp.hostname = "$host"

         |akka.remote.netty.tcp.port = "$port"

       """.stripMargin

    val conf = ConfigFactory.parseString(confStr)

    val actorSystem = ActorSystem(MASTER_SYSTEM, conf)

    val actor = actorSystem.actorOf(Props(new TestMaster(host, port)), MASTER_NAME)

    actorSystem.awaitTermination()

  }

 

}

B)、客户端

package test.cn.****.test

 

import akka.actor.Actor

import com.typesafe.config.ConfigFactory

import akka.actor.ActorSystem

import akka.actor.ActorSelection

import akka.actor.Props

import java.util.UUID

import scala.concurrent.duration._

 

class TestWoker(val cores: Int, val memory: Int, val masterHost: String, val masterPort: Int) extends Actor {

  // master 的URL

  var masterUrl: String = _

  // master的引用  

  var master: ActorSelection = _

  // 定时时间

  val HEARTBEAT_INTERVAL = 10000

  // woker的ID

  val wokerId = UUID.randomUUID().toString()

  override def preStart(): Unit = {

    master = context.actorSelection(s"akka.tcp://${TestMaster.MASTER_SYSTEM}@$masterHost:$masterPort/user/${TestMaster.MASTER_NAME}")

    println("preStart:" + UUID.randomUUID().toString())

    // 向master发送注册信息

    master ! TestRegisterWorker(wokerId, cores, memory)

  }

 

  def receive: Receive = {

    // 注册完成后master发送给woker的信息

    case TestRegisterdWorker(masterUrl) => {

      this.masterUrl = masterUrl

      // 启动定时任务,定时的向master发送心跳

      import context.dispatcher

      context.system.scheduler.schedule(0 milli, HEARTBEAT_INTERVAL milli, self, TestSendHeartbeat)

    }

 

    // 定时向master发送心跳

    case TestSendHeartbeat => {

      println("TestSendHeartbeat:" + UUID.randomUUID().toString())

      master ! TestHeartbeat(wokerId)

    }

 

  }

}

 

object TestWoker {

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

    // woker的信息

    val host = "127.0.0.1"

    val port = 9999

    val cores = 4

    val memory = 1024

 

    // master的信息

    val masterHost = "127.0.0.1"

    val masterPort = 8888

 

    val confStr = s"""

         |akka.actor.provider = "akka.remote.RemoteActorRefProvider"

         |akka.remote.netty.tcp.hostname = "$host"

         |akka.remote.netty.tcp.port = "$port"

       """.stripMargin

    val conf = ConfigFactory.parseString(confStr)

    val actorSystem = ActorSystem("TestWokerActorSystem", conf)

    val actor = actorSystem.actorOf(Props(new TestWoker(cores, memory, masterHost, masterPort)), "TestWoker")

    actorSystem.awaitTermination()

  }

}

C)、接口端

package test.cn.****.test

// 定义接口

trait TestMessage extends Serializable

 

// woker -> master 发送注册信息

case class TestRegisterWorker(workerId: String, cores: Int, memory: Int) extends TestMessage

 

// master -> woker 注册成功信息

case class TestRegisterdWorker(masterUrl: String) extends TestMessage

 

// woker 向 master 发送心跳

case class TestHeartbeat(wokerId: String)

 

// woker  初始化的信息

case object TestSendHeartbeat extends TestMessage

 

// 检查超时的时间

case object TestCheckTimeOutWorker extends TestMessage

D)、构造器端

package test.cn.****.test

 

class TestWorkerInfo(val wokerId: String, val cores: Int, val memory: Int) {

  var lastHeartbeatTime: Long = _

}

 

 

 

PageRank 算法计算权重

package com.sdcet

 

import org.apache.spark.rdd.RDD

import org.apache.spark.{SparkConf, SparkContext}

 

/**

  * Created by Administrator on 2017/2/10.

  */

object PageRank {

  def main(args: Array[String]) {

    System.setProperty("hadoop.home.dir", "E:\\winutils-hadoop-2.6.4\\hadoop-2.6.4")

    val conf = new SparkConf().setAppName("PageRank").setMaster("local")

    val sc = new SparkContext(conf)

    val links: RDD[(String, Array[String])] = sc.parallelize(Array(("A", Array("d")), ("B", Array("A")), ("C", Array("A", "B")), ("D", Array("A", "C"))), 2)

    var rank: RDD[(String, Double)] = sc.parallelize(Array(("A", 1.0), ("B", 1.0), ("C", 1.0), ("D", 1.0)), 2)

    for (i <- 1 to 10) {

      val contribs = links.join(rank, 2).flatMap {

        case (url, (links, rank)) => links.map(dest => (dest, rank / links.size))

      }

      rank = contribs.reduceByKey(_ + _, 2).mapValues(0.15 + 0.85 * _)

    }

println("rank:"+rank)

 

    rank.saveAsTextFile("hdfs://hadoop1:9000/pageRank")

  }

}

 

Scala 面试题

1-1)、接口&类&APP方法

A)、接口

trait Logger {
  def log(msg: String): Unit = {
    println("log:" + msg)
  }
}

B)、类

class ConcreteLogger extends Logger {
  def concreatelog(): Unit = {
    log("hello scala")
  }
}

C)、APP实现方法

object UserTrait extends App {
  val log = new ConcreteLogger
  log.concreatelog()
}

D)、结果

 

E)、原因

 

猜你喜欢

转载自blog.csdn.net/xfg0218/article/details/82381647