关于Scala那些事儿

今天也要加油鸭~

  • 这是一份总结的学习笔记
  • 路漫漫其修远兮,吾将上下而求索
  • 可阅读可评论可分享可转载,希望向优秀的人学习

前言

Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。Scala 运行在Java虚拟机上,并兼容现有的Java程序。java、Scala都是基于JVM的编程语言(文件编译成class文件保存),类相互之间可以调用,Scala并可以调用现有的Java类库;Spark1.6中使用的是Sacla2.10。

  • 面向过程:需要你自己去一步一步的执行
  • 面向函数:也是需要自己去一步一步执行,只是执行的过程已经提前设定好了
  • 面向对象:让机器人去执行 ,因为已经设定好执行步骤,你只需等待结果就好了

总的来说:面向对象是将事物高度抽象化,面向对象必须先建立抽象模型,之后直接使用模型就行了;面向过程是一种自顶向下的编程。

一、Scala官网6个特征

1).Java和scala可以混编(面向对象的其他语言之间类互相调用)
2).类型推测(自动推测类型,不用指定类型,跟JS类似)
3).支持并发和分布式(Actor通信,比如线程与线程之间通信)
4).trait特质,特征(类似java中interfaces 和 abstract结合)
5).模式匹配(类似java中switch case,Scala可以类型/值匹配,java不可类型匹配)
6).高阶函数(不仅返回数值,还能返回函数)

二、Scala安装使用

windows安装,配置环境变量

  • 官网下载scala2.10:Scala官网
    • 1、下载好后安装。双击msi包安装,记住安装的路径。
      • 配置环境变量(和配置jdk一样):
      • 新建SCALA_HOME
      • 上个步骤完成后,编辑Path变量,在后面追加如下:;%SCALA_HOME%\bin;%SCALA_HOME%\jre\bin(可不加)
      • 打开cmd,输入:scala - version 看是否显示版本号,确定是否安装成功
    • 2、eclipse 配置scala插件:下载插件(一定要对应eclipse版本下载)Scala插件
      • 下载解压之后,将features和plugins两个文件夹拷贝到eclipse安装目录中的” dropins/scala”目录下。进入dropins,新建scala文件夹,将两个文件夹拷贝到“dropins/scala”下
    • 3、scala ide(官方配置好的eclipse插件)
      下载网址:eclipse插件

三、Scala基础

  • 知识总结:
    类和对象;
    定义变量用var,定义常量用val;
    类可以传参,有参数就有默认构造
    类中的属性有getter,setter方法;
    重写构造,第一行先调用默认的构造;
    当new classs时,类中除了方法不执行其他都执行;
    伴生类和伴生对象。
1、数据类型数据类型子类父类

数据类型

2、变量和常量的声明
基本语法

编译性语言:

/**
1、Scala object 相当于java中的单例,object中定义的是静态的东西
2、定义变量使用var,变量可变。定义常量使用val,常量不可变。会有类型自动推断
3、Scala中一行后面可以不加“;”,有分号自动推断机制,一行语句有多条语句要分号
4、scala类中的属性默认就有getter,setter方法;类可以传参,传参就有了默认的构造。类重写构造,第一行首先调用默认构造。
Scala当new类的时候,除了方法(不包含构造)不执行,其他都执行,方法需要调用
5、伴生类和伴生对象,在一个Scala文件中,如果在同一个文件中,object对象和class类的名称相同,则这个对象就是这个类的伴生对象,这个类就是这个对象的伴生类。可以互相访问私有变量。
**/
class Person(xname:String, xage:Int){
	(private) val name = xname
	var age = xage
	var gender = 'm'
	//重写构造
	def this(yname:String, yage:Int, ygender:Char){
		this(yname, yage)
		this.gender = ygender
	}
	def show() = {
		println('score is ' + ClassAndObject.score)
		
	}
}
object ClassAndObject{
	val score = 1000
	def main(args: Array[string]):unit = {
		val a: Double = 100
		println(a)
		//类和对象
		val person = new Person('lisi',19,'f')
		person.show()
		println(person.name)
		println(person.age)
		println(person.gender)
	}
}

伴生类和伴生对象

class Person(xname :String , xage :Int){
  var name = Person.name
  val age = xage
  var gender = "m"
  def this(name:String,age:Int,g:String){
    this(name,age)
    gender = g
  }
  
  def sayName() = {
    "my name is "+ name
  }

}

object Person {
  val name = "zhangsanfeng"
  
  def main(args: Array[String]): Unit = {
    val person = new Person("wagnwu",10,"f")
    println(person.age);
    println(person.sayName())
    println(person.gender)
  }
}

If else

  /**
     * if else 
     */
    val age =18 
    if (age < 18 ){
    	println("no allow")
    }else if (18<=age&&age<=20){
    	println("allow with other")
    }else{
    	println("allow self")
    }

for循环

	println(1 to 10) //range(1,...,10)
	println(1 to (10,2)) //range(1,3,5,7,9)
	println(1 until 10) //range(1,...,9)
	
	for(i < -1 to 10){
		println(i)  //1,...,10
	}
	
	//多层循环
	//可以分号隔开,写入多个list赋值的变量,构成多层for循环
    //scala中 不能写count++ count-- 只能写count+
    var count = 0;
    for(i <- 1 to 10; j <- 1 until 10){
      println("i="+ i +",	j="+j)
      count += 1
    }
    println(count);
    
    //例子: 打印九九乘法表(双层循环)
    for(i <- 1 until 10 ;j <- 1 until 10){
      if(i>=j){
    	  print(i +" * " + j + " = "+ i*j+"	")
        
      }
      if(i==j ){
        println()
      }  
    }
    #for循环用yield 关键字返回一个集合
    val result = for(i <- 1 to 100;if(i%2==0) if(i>50)) yield i
    println(result)

while

	var i = 0
	while(i < 100){
		println("第" + i + "次")
		i += 1
		#5.scala中不能使用count++,count—只能使用count = count+1 ,			   count += 1
	}
Scala函数
object test{
    //1、方法的定义
   //(1)方法返回值一般省略,若不省略要显示申明方法的返回类型
    //(2)方法返回值可以省略,会自动推断,会将方法体最后一行计算的结果作为返回值返回
    //(3)如果方法体可以一行搞定,方法的{}可以省略
    //(4)定义方法的等号=如果省略,那么无论方法体最后一行计算的结果是什么都会丢弃返回unit(结果会显示括号)
	def main(args: Array[String]): Unit ={
		def max(x:Int, y:Int) = {
			if(x>y) x else y
		}
	}
}

递归方法

//2.递归方法需要显示的申明方法的返回类型
	def fun(x:Int):Int = {
		if(a == 1){
			1
		}else{
			a* fun(a-1)
		}
	}
//3.参数有默认值的方法
	def fun(a: Int=100, b:Int=50) = {
		a+b
	}
	println(fun(b=20)) //输出120(100+20)
//4.可变长参数的方法
	def fun(ss:String*) = {
		for(elem <- ss){
			println(elem)
		}
		//ss.foreach(s=>{
			println(s) /***=>是匿名函数,同样是遍历***/
		})
		//当匿名函数参数只显示一次时可简化 ss.foreach(println(_))参数只有一次的时候,可以简化(_):ss.foreach(println)
	fun('q','a','v')
//5.匿名函数: =>
	//无参数
	val fun = ()=>{
		println("hello world")
	}
	fun()
	//有参数
	val fun1 = (s:String)=>{
		println(s)
	}
//6.嵌套方法
	def fun(num: Int)= {
		def fun1(a: Int){
			if(a==1){
				a
			}else{
				a*fun(a-1)
			}
		}
		fun1(num)
	}
	println(fun(10))
//7.偏应用函数
	def showlog(date:Date, log:String) = {
		println("date is" + date+",log is" + log)
	}
	val date1 = new date()
	//只有某一个参数变化
	val fun = showlog(data1:Date,_:String)
	fun("aaa")
//8.高级函数:1)函数的参数是函数;2)函数的返回是函数;3)函数的参数和返回都是函数
	def fun(a:Int, b:Int): String = {
		a+b+"~"
	}
	def fun1(f:(Int,Int)=>String,x:Int): String={
		val result = f(100,200)
		result+"@"+x
	}
	println(fun1(fun,111)) //'300~@111'
	val result = fun1((a:Int,b:Int)=>{
		a+"~"+b
	},100)
	
	//函数的返回是函数:必须显示申明方法的返回类型是函数
	def fun(a:Int, b:Int):(Int,Int)=>Int ={
		val result = a+b
		def fun1(x:Int, y:Int): Int ={
			x+y+result
		}
		fun1
	}
	println(fun(1,2)(100,200)) //输出303
	//函数的返回和参数是函数
	def fun(f:(Int,Int)=>Int):(String,String)=>String={
		val result = f(1,2)
		def fun1(s1:String, s2:String): String ={
			s1+s2+result
		}
		fun1
	}
	fun((a:Int,b:Int)=>{a*b})("hello","world")
	
//9.柯里化函数:高阶函数的简化
	def fun(a:Int,b:Int)(c:Int,d:Int) = {
		a+b+c+d
	}
	println(fun(1,2)(3,4))
}
集合

Array:数组
1.创建数组
new ArrayInt
赋值:arr(0) = xxx
ArrayString
2.数组遍历
for
foreach
3.创建一维数组和二维数组
4.数组中方法举例
Array.concate:合并数组
Array.fill(5)(“hello”):创建初始值的定长数组

object Array_test{
	def main(args:Array[String]): Unit = {
		//合并
		val t1 = Array(1,2,3)
		val t2 = Array(4,5,6)
		val result = Array.concat(t1,t2)
	 	//初始化五个长度为2的数组
		Array.fill(5,2)("help")
		val arr1 = Array[Int](1,2,3,4)
		arr1.foreach(println)
		//两种方法
		val arr = new Array[Int][3]  //指定长度
		arr[0] = 100
		arr[1] = 200
		arr[2] = 300
		arr.foreach(println)
	}
} 

List:跟定义的顺序一致,有序
1.创建list
val list = List(1,2,3,4)
Nil长度为0的list
2.list遍历
foreach ,for
3.list方法举例
filter:过滤元素
count:计算符合条件的元素个数
map:对元素操作
flatmap :压扁扁平,先map再flat
flatmap vs map

object List_test{
	def main(args:Array[String]): Unit = {
		val list = List[String]("hello world","hello word","hello wod")
		val result = list.map(s=>{
			s.split(" ")
		})
		//将切分分为多个Array,来一条出来一个对象(一对一)
		result.foreach(arr=>{
			arr.foreach(println)
		})
		//直接将String返回一个,一对多(先map后flat)
		val result2 = list.flatmap(s=>{
			s.split(" ")
		})	
		result2.foreach(println)
		
		val result = list.filter(s=>{
			s.equals("hello world")
		})	
	}	
}

set,无序
1.创建set
注意:set集合会自动去重
2.set遍历
foreach,for
3.set方法举例
交集:intersect ,&
差集: diff ,&~
子集:subsetOf
最大:max
最小:min
转成数组,toList
转成字符串:mkString(“~”)

object set_test{
	def main(args:Array[String]): Unit={
		val set = Set[Int](1,2,3,4,5)
		val set1 = Set[Int](1,2,3,6,7)
		val result = set.diff(set1)
		result.foreach(println)
	}
}

map
1.map创建
Map(1 –>”hell0’)
Map((1,”hello”))
注意:创建map时,相同的key被后面的相同的key顶替掉,只保留一个
2.获取map的值
map.get(“1”).get
map.get(100).getOrElse(“no value”):如果map中没有对应项,赋值为getOrElse传的值。
option:包含some和none
获取所有的values – map.values
3.合并map
++ 例:map1.++(map2) --map1中加入map2
++: 例:map1.++:(map2) –map2中加入map1
注意:合并map会将map中的相同key的value替换

object map_test{
	def main(args:Array[String]): Unit={
		val map = Map("1"->"a", "2"->"b",("3","c"),("3","cc"))
		val result = map.get("3").getOrElse("XXX")		
		val keys = map.keys
		val value = map.values
		for(key<- keys){
			println("key="+key, "value =" +map.get(key).get )
		}
	}
}

元组tuple
元组定义:与列表一样,与列表不同的是元组可以包含不同类型的元素。元组的值是通过将单个的值包含在圆括号中构成的。

  1. 创建元组与取值
    val tuple = new Tuple(1) 可以使用new
    val tuple2 = Tuple(1,2) 可以不使用new,也可以直接写成val tuple3 =(1,2,3)
    取值用”._XX” 可以获取元组中的值
    注意:tuple最多支持22个参数
  2. 元组的遍历
    tuple.productlterator得到迭代器,进而遍历
	val tuplelterator = tuple22.productlterator
	while(tuplelterator.hasnext()){
		println(tuplelterator.next())
	}
  1. tuple2 swap交换: swap,toString方法
    注意:swap元素翻转,只针对二元组
    //翻转,只针对二元组
    println(tuple2.swap)
    //toString
    println(tuple3.toString())
Trait特质特征
  1. 概念理解
    Scala Trait(特征) 相当于java中的抽象类和接口的集合,实际上它比接口还功能强大。
    与接口不同的是,它还可以定义属性和方法的实现。
    一般情况下Scala的类可以继承多个Trait,从结果来看就是实现了多重继承。Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait。
  2. 举例:trait中带属性带方法实现
    注意:
    继承的多个trait中如果有同名的方法和属性,必须要在类中使用“override”重新定义。
    trait中不可以传参数,里面可以写方法,方法体,变量,常量
  3. 类继承多个trait,第一个关键字使用extends,之后使用with
trait read{
	val readType = "Read"
	val gender = "m"
	def read(name:String){
		println(name+ "is reading")
	}
}
trait Listen{
	val listentype = "Listen"
	val gender = "m"
	def listen(name:String){
		println(name+ "is listening")
	}
}
//继承多个trait
class Person() extends Read with Listen{
	override val gender = "f"
}
object test{
	def main(args:Array[String]):Unit = {
		val person = new Person()
		person.read("wangwu")
		person.listen("xiaoming")
	}
}
//trait中带方法不实现
trait Equal {
  def isEqual(x: Any): Boolean
  def isNotEqual(x: Any): Boolean = !isEqual(x)
}
class Point(xc: Int, yc: Int) extends Equal {
  var x: Int = xc
  var y: Int = yc
  def isEqual(obj: Any) =
    obj.isInstanceOf[Point] &&
    obj.asInstanceOf[Point].x == x
}
object Test {
   def main(args: Array[String]) {
      val p1 = new Point(2, 3)
      val p2 = new Point(2, 4)
      val p3 = new Point(3, 3)

      println(p1.isNotEqual(p2))
      println(p1.isNotEqual(p3))
      println(p1.isNotEqual(2))
   }
}
模式匹配
  1. 概念理解:相当于java中的switch …case…
    Scala 提供了强大的模式匹配机制,应用也非常广泛;
    一个模式匹配包含了一系列备选项,每个都开始于关键字 case;
    每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。
  2. 代码及注意点
  • 模式匹配(match)不仅可以匹配值还可以匹配类型
  • 从上到下顺序匹配,如果匹配到则不再往下匹配;
  • case_=>{…}都匹配不上时,会匹配到case _ ,相当于default,要放到最后;
  • match 的最外面的”{ }”可以去掉看成一个语句;
    匹配过程中会有数值转化;case s: String=>{…}匹配类型;case 100=>{…}匹配值。
object Test {
   def main(args: Array[String]) {
      println(matchTest("two")) //2
      println(matchTest("test")) //many
      println(matchTest(1)) //one
      println(matchTest(6)) //scala.Int
   }
   def matchTest(x: Any): Any = x match {
      case 1 => "one"
      case "two" => 2
      case y: Int => "scala.Int"
      case _ => "many"
   }
}
case 样例类
  1. 概念理解
    使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类。实现了类构造参数的getter方法(构造参数默认被声明为val),当构造参数是声明为var类型的,它将帮你实现setter和getter方法。
  • 样例类默认帮你实现了toString,equals,copy和hashCode等方法。
  • 样例类可以new, 也可以不用new
case class Person1(name:String,age:Int)

object Lesson_CaseClass {
  def main(args: Array[String]): Unit = {
    val p1 = new Person1("zhangsan",10)
    val p2 = Person1("lisi",20)
    val p3 = Person1("wangwu",30)
    
    val list = List(p1,p2,p3)
    list.foreach { x => {
      x match {
        case Person1("zhangsan",10) => println("zhangsan")
        case Person1("lisi",20) => println("lisi")
        case _ => println("no match")
      }
    } }
Actor
  1. 概念理解
    Actor Model是用来编写并行计算或分布式系统的高层次抽象(类似java中的Thread)让程序员不必为多线程模式下共享锁而烦恼,被用在Erlang 语言上, 高可用性99.9999999 % 一年只有31ms 宕机Actors将状态和行为封装在一个轻量的进程/线程中,但是不和其他Actors分享状态,每个Actors有自己的世界观,当需要和其他Actors交互时,通过发送事件和消息,发送是异步的,非堵塞的(fire-andforget),发送消息后不必等另外Actors回复,也不必暂停,每个Actors有自己的消息队列,进来的消息按先来后到排列,这就有很好的并发策略和可伸缩性,可以建立性能很好的事件驱动系统。
    Actor的特征:
  • ActorModel是消息传递模型,基本特征就是消息传递
  • 消息发送是异步的,非阻塞的
  • 消息一旦发送成功,不能修改
  • Actor之间传递时,自己决定决定去检查消息,而不是一直等待,是异步非阻塞的(Actor会不定期检查)
    什么是Akka
    Akka 是一个用 Scala 编写的库,用于简化编写容错的、高可伸缩性的 Java 和Scala 的 Actor 模型应用,底层实现就是Actor,Akka是一个开发库和运行环境,可以用于构建高并发、分布式、可容错、事件驱动的基于JVM的应用。使构建高并发的分布式应用更加容易。
    spark1.6之前的底层节点间通信使用的是Akka(多线程框架),Akka是一个通信模型,底层是actor实现,actor也是一个通信模型(类似于java中的多线程编程)。1.6之后使用的netty传输。
    Actor发送消息之后,消息不能改变,发送到其他Actor的通信邮箱排队处理,发送消息一端不必等待处理结果结束,可以去执行其他任务
    如果当前Actor的请求被处理,会将结果通知到当前Actor的结果邮箱,
  1. 给Actor发送消息
import scala.actors.Actor

class myActor extends Actor{
	def act(){
		while(true){
			receive{
				case x: String => println("get String" + x)
				case x: Int =>println("get Int")
				case _=> println("get default")
			}
		}
	}
}
object Actor_test{
	def main(args:Arrat[String]):Unit = {
		//创建actor的消息接受和传递
		val actor = new myActor()
		//启动
		actor.start()
		//发送消息写法
		actor ! "I love you"
	}
}
  1. Actor和Actor之间发送消息
case class Message(actor:Actor,msg:Any)

class Actor1 extends Actor{
  def act(){
    while(true){
      receive{
        case  msg :Message => {
          println("i sava msg! = "+ msg.msg)
          
          msg.actor!"i love you too !"
          }
        case msg :String => println(msg)
        case  _ => println("default msg!")
      }
    }
  }
}

class Actor2(actor :Actor) extends Actor{
  actor ! Message(this,"i love you !")
	def act(){
		while(true){
			receive{
  			case msg :String => {
  			  if(msg.equals("i love you too !")){
  			    println(msg)
  			   actor! "could we have a date !"
  			  }
  			}
  			case  _ => println("default msg!")
			}
		}
	}
}

object test_Actor2 {
  def main(args: Array[String]): Unit = {
    val actor1 = new Actor1()
    actor1.start()
    val actor2 = new Actor2(actor1)
    actor2.start()
  }
}  

四、项目-spark wordcount

重点://用一行实现wordcount
sc.textFile(“路径”).flatMap{.split(" ")}.map{(,1)}.reduceByKey(+).foreach(println)

package com.spark
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.rdd.RDD.rddToPairRDDFunctions

object SparkWordCount{
	def main(args:Array[String]):Unit ={
		val conf = new SparkConf().setAppName("wordcount").setMaster("local")
		val sc = new SparkContext(conf)
		
		val lines: RDD[String] = sc.textFile("./words")
		//切分
		val words = lines.flatMap(line=>{
			line.split(" ")
		})
		//返回元组
		val pairWords:RDD[(String, Int)] = words.map(word=>{
			new Tuple2(word,1)
		})
		//reduceByKey 先分组,再给每个组的value进行聚合
		val result:RDD[(String, Int)] = 		pairWords.reduceBykey((v1,v2)=>{
			v1+v2  //第一条和第二条value相加,
		})
		result.foreach(tuple=>{
			println(tuple)
		})		
//用一行实现wordcount
		sc.textFile("./words").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).foreach(println)
		//对result的值排序--降序
		result.sortBy(tuple=>{tuple._2},flase)
		result.foreach(tuple=>{
			println(tuple)
		})
		sc.stop()
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值