Scala

Scala

大数据中两个重要概念

一:分布式,垂直分割保证各司其职(洗菜,切菜,炒菜…)

二:集群,水平扩展解决高并发(多个人洗菜,多个人切菜,多个人炒菜…)

idea出品的Kotlin改变了安卓开发

1、引言

Scala编程语言(大数据领域 Spark Kafka)
特点:
1.面向对象编程语言(优先考虑传递数据)(落脚点:把现实问题抽象为实体类,Service建模)
2.面向函数式编程,专门为数据而生语言(优先考虑传递函数方法)(有多种编程方式)
3.强大的数组集合计算能力(落脚点:数据的分析和计算)
JVM类型的编程语言(不同操作系统的解合,clojure,jpython,jjavaScript都是运行在jvm之上)
为什么需要Scala运行在虚拟机上?
	1.天生屏蔽操作系统OS之间的差异
	2.无缝对接java(降低程序员的学习成本)
Scala怎么运行在JVM虚拟机上?
	1.把Scala源码编译成.class文件(编译器)
(面试坑)Scala慢不慢?
	不慢,至少和java代码相比没差,都是.class文件
为什么要学习scala
现在主流大数据计算框架对Scala编程比较友好,例如:Kafka.0.11.0_2.11.tar.gz(后面是scala语言版本)、Spark使用Scala(导致使用Scala语言可以 高效 的实现数据的分析处理)

2、Scala的安装

​ Scala版本不要过新要配合后面的Spark

运行命令  scala 进入 scala交互页面
  1. scala(windows的安装)
    下一步默认安装(默认安装路径不好使就装到某个盘符的根目录下)
  2. scala(linux的安装)
    rpm -ivh sacala–xxx–.rpm
rpm 安装:默认安装在usr/下(自动做了make install放到usr/bin下)
[root@hive1 ~]# rpm -ivh scala-2.11.12.rpm

#查找存放的位置
[root@hive1 ~]# which scala
/usr/bin/scala

3、常见变量

Scala是纯粹的面向对象编程语言(Java做对比,基本类型和对象类型),在Scala没有基本类型,所有值类型都是AnyVal的子类,所有对象类型都是AnyRef的子类。一般所有的AnyVal类型都有字面值,所有AnyRef类型默认值都是Null。所有类型都属于对象类型。

在这里插入图片描述

变量声明

Java变量声明

变量类型 变量名 = 变量值;
int a = 1;

Scala变量声明(有强大的类型推断能力)

(var|val)变量名[:变量类型] = 变量值[:变量类型]
 变量 | 常量
Scala>var i:Int = 1:Int
i:Int = 1

scala>var i = 1
i:Int = 1

scala>var i:Byte = 1
i:Byte = 1

scala>var i = 1:Byte
i:Byte = 1

scala>i = 127
i:Byte = 127
scala> i=128
<console>:12: error: type mismatch;
found : Int(128)
required: Byte
i=128
^

正常情况下用户可以省略类型,因为Scala可以根据字面量自动推断出变量的类型,所以在定义一个用户只需要指明该变量时是变量还是常量即可。

scala> var j = "hello scala"
j:String = hello scala
scala> var sex = true
sex:Boolean = true
scala>sex = "false"
<console>:12: error: type mismatch;
found : String("false")
required: Boolean
sex="false"

注意var修饰变量值可以改变,val修饰常量 值不可改变等价于Java中final修饰的变量

Scala> var i = 10
i:Int = 10
scala> i = 11
i:Int = 11
scala> val j = 10
j:Int = 10
scala> j = 11
<console>:12: error: reassignment to val
j=11
^
数值转换
  • 类型兼容且有小到大,由整数到小数,可以自动类型提升

    scala> var i:Byte = 1
    i:Byte = 1
    scala> var j:Byte = 1
    j:Byte = 1
    scala> var k = i + j
    k:Int = 2
    scala>var m = k + 0.5
    m:Double = 2.5
    m: Double = 2.5
    scala> var f:Float=m
    <console>:12: error: type mismatch;
    found : Double
    required: Float
    var f:Float=m
    ^ 
    
  • 类型兼容,且由大到小asInstanceOf,例如:Long转换Int,Double转换为Float

    scala> var d:Double = 100.0
    d: Double = 100.0
    scala> var f:Float = d
    <console>:12: error: type mismatch;
    found : Double
    required: Float
    var f:Float = d
    ^
    scala> var f:Float = d.asInstanceOf[Float]
    f:Float = 100.0
    

    在Scala中[]表示的是泛型

  • 将字符串类型转为数值类型 toXXX

    scala> var sex = true
    sex:Boolean = true
    scala> sex = "flase"
    <console>:12: error: type mismatch;
    found : String("false")
    required: Boolean
    sex="false"
    ^
    scala> sex = "flase".toBoolean
    scala> var i = 11
    i:Int = 1
    scala> i = "123".toInt
    i:Int = 123
    

    注意在类型兼容的前提下 大->小 使用asInstanceOf[类型]

    如果是字符串类型转为值类型可以用toInt/toDouble/toFloat/toByte/toShort

Unit类型

在Scala中通常会使用Unit关键字表示一种特殊的返回值类型,等价于Java中的Void关键字。但是在Scala中Unit是有字面量的

scala> var u:Unit=() #值是:空元组
u: Unit = ()
Array类型(数组类型)
scala> var a:Array[Int] = new Array[Int](5)#直接指定数组大小,并且赋值默认值0
a: Array[Int] = Array(0.0.0.0.0)
scala> var a:Array[Int] = Array(1,2,3,4,5)#一种快速创建复杂对象方式(伴生对象)【调用了工厂方法,底层还是new对象】
a:Array[Int] = Array(1,2,3,4,5)
scala> a.length		#获取数组的长度
scala> a.size		#获取数组的长度
scala> a(0) = -1	#修改数据的0下标的内容(-1前面要有空格)
scala> a
res9:Array[Int] = Array(-1,2,3,4,5)
scala> a(5) = -1	#下标越界
java.lang.ArrayIndexOutOfBoundsException: 5
... 32 elided
元组(Tuple)

由若干个元素构成的 复合变量

scala> var user = (1,"韩梅梅",18,true)
user:(Int,String,Int,Boolean) = (1,韩梅梅,18,true)

scala> var a:(String,Int) = ("Hello Scala",1)
a:(String,Int) = (Hello Scala,1)

scala> user._1	#访问元组中第几个元素,下标从1开始,最多到22
res12: Int = 1

scala> user.1 = 2	#元组中的元素都是val,不允许修改
<console>:12: error: reassignment to val

元组中元素都是只读的,一般有值类型和String类型构成。在Scala一个Tuple中最多能够有22个成员。

元组中的元素都是val类型不允许修改(只读),但是元组变量值可以修改

scala> var user = ("zhangsan",18,true,15000)
user: (String,Int,Boolean,Int) = (zhangsan,18,true,15000)

scala> user = ("wangwu",20,false,20000)
user: (String,Int,Boolean,Int) = (wangwu,20,false,20000)

4、分支循环

if条件分支
语法
    var a:Int = new Random().nextInt(100);
    if(a<10){
      println("小可爱");
    }else if (a>=10 && a<30){
      println("臭弟弟");
    }else{
      println("老男人")
    }

和java不同,if可以将修饰的代码块的返回值给一个变量

var a:Int = new Random().nextInt(100);
var b = if(a<=10){
      "小可爱"
    }else if(a<=20){
      "臭弟弟"
    }else{
      "老东西"
    }
    println(s"结果:${b},哈哈哈")

while、do-while

在scala中while和do-while没有continue和break关键字

    var b = 5
    while (b>0){
      println(b)
      b-=1
    }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    do{
      println(b)
      b -= 1
    }while(b>0)
Breaks

Scala 语言中默认没有break语句,但是在Scala2.8版本后可以使用另外一种方式实现break语句。当在循环中使用break语句,在执行到该语句时,就会中断循环并执行循环体之后的代码来块。

var b = 5 
var breaks = new Breaks
    breaks.breakable({
      do{
        print(b)
        b-=1
        if(b<=3){
          breaks.break()
        }
      }while(b>0)
    })
for循环(重点)
  • 迭代遍历数组

        var array = Array(1,2,3,4)
        for(item<- array){println(item)}
    
  • 下标遍历数据

    var array = Array(1,2,3,4)
    for(i<- 0 to array.length-1){println(array(i))}		//to 	包含
    for(i <- 0 until(array.size)){println(array(i))}	//until 不包含
    
  • for可使用多个循环因子

    for(int i <- 1 to 9;j <- 1 to i){
        print(s"${j}*${i}="+i*j+" ")
        if(i==j){println()}
    }
    
  • for 和if的使用(控制步数)

    for(i <- 0 to 10;if(i%2==0)){
        println(i)
    }
    
  • for和yield关键字实现元素的提取,创建子集【重点】

    var array = Array(1,2,3,4)
    var res = for(i<-array) yield 2*i
    for(a<-res){
        println(a)
    }
    
    2	4	6	8	
    
match-case(模式匹配)

在scala中剔除java中switch语句,提供了match-case替代方案,该方案不仅仅可以按照值匹配,还可以按照类型、以及值的结构(数组匹配,元组匹配,case-class匹配等)

  • 值匹配

    	var c = Array(1,2)
        var d = c(new Random().nextInt(2))
        var e = d match{
          case 1 =>"one"
          case 2 =>"two"
          case _ =>"three"
    
        }
        println(e)
    
  • 类型匹配

    	var c = Array(1,"suns")
        var d = c(new Random().nextInt(2))
        var e = d match {
          case h:Int => s"id:${h}"
          case h:String => s"name:${h}"
          case default => null
        }
        println(e)
    

    注意:_ 表示默认匹配等价 default关键字

5、函数|方法

在scala中函数方法都是对象,一样

def专门修饰函数|方法 变量

√标准函数
scala> def sum(x:Int,y:Int):Int={
     |   x+y
     | }
sum: (x: Int, y: Int)Int

一般情况下,如果函数体最后一行作为函数的返回值,一般可以省略函数的返回值类型,例如

scala> def sum(x:Int,y:Int)={
     |   x+y
     | }
sum: (x: Int, y: Int)Int

scala> def sum(x:Int,y:Int):Int={
     |   return x+y
     | }
sum: (x: Int, y: Int)Int

如果有return语句,函数不能省略返回值类型

scala> def sum(x:Int,y:Int)={
     |   return x+y
     | }
<console>:12: error: method sum has return statement; needs result type
        return x+y
        ^
可变常参数
scala> def sum(values:Int*):Int={
     |   var total=0
     |   for( i<- values) total += i
     |   total
     | }
sum: (values: Int*)Int

scala> sum(1,2,3,4,5)
res9: Int = 15

scala> def sayHi(msg:String,names:String*):Unit={
     |   for(name <- names){
     |           println(msg+"\t"+name)
     |   }
     | }
sayHi: (msg: String, names: String*)Unit

scala> sayHi("Hello","zs")
Hello   zs

可变长参数必须放置在最后一位 一个方法的可变长参数有且仅有一个

scala> def sayHi(names:String*,msg:String):Unit={
     |   for(name <- names){
     |           println(msg+"\t"+name)
     |   }
     | }
<console>:11: error: *-parameter must come last
       def sayHi(names:String*,msg:String):Unit={
                 ^
           
#可变长参数用命名参数不好使      
scala> sayHi(names="li",msg="Hello",names="hua")
<console>:13: error: parameter 'names' is already specified at parameter position 1
Note that 'msg' is not a parameter name of the invoked method.
       sayHi(names="li",msg="Hello",names="hua")
命名参数
scala> def sayHi(name:String,msg:String):Unit={
     |   println(s"${msg}\t${name}")
     | }
scala> sayHi(msg="hello",name="zhangsan")
hello   zhangsan

参数默认值
scala> def sayHi(name:String="未知",msg:String="哈喽"):Unit={
     |   println(s"${msg}\t${name}")
     | }
sayHi: (name: String, msg: String)Unit

scala> sayHi("zhangsan")
哈喽    zhangsan

scala> sayHi(msg="hello")
hello    未知
scala> sayHi("zhangsan","nihao")
nihao   zhangsan
内嵌函数(没有要求)

求阶乘案例

def jc2(num:Int):Int={
    def compute(x:Int):Int={
        if(x>1){
            x*compute(x-1)
        }else{
            1
        }
    }
    compute(num)
}

def jc(num:Int):Int={
    if(num>1){
        num*jc(num-1)
    }else{
        1
    }
}
√柯里化

在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。可以传递部分参数

def sum1(x:Int,y:Int): Int ={
    x+y
}
def sum2(x:Int)(y:Int): Int ={
    x+y
}
√匿名函数(精华)

将定义函数,以变量形式表达。
在这里插入图片描述

scala> def sum(x:Int,y:Int): Int ={
     |     x+y
     |   }
sum: (x: Int, y: Int)Int

scala> sum _
res38: (Int, Int) => Int = <function2>
变量名:  变量类型            变量值
//第一种形式
val sum:(Int,Int)=>Int  = (x,y)=> x+y
--
val i:Int=1
//第二种形式
val sum = (x:Int,y:Int)=> x+y
--
val i=1
//第三种形式
val sum = ((x,y)=> x+y):((Int,Int)=>Int)
--
val i=1:Byte
def sum:(Int,Int)=>Int  = (x,y)=> x+y
def sum=(x:Int,y:Int)=>  x+y

通过以上写法得到:
1)任意一个函数,可以转变成函数式变量。

2)在Scala一切皆对象,因此变量也是对象

函数 = = 特殊变量 (函数变量|匿名函数)== 对象

scala> def j=1 //定义的是一个常量函数。而不是变量
j: Int
scala> j=10
<console>:12: error: value j_= is not a member of object $iw
       j=10
       ^

6、面向对象(只是为了看源码)

Object(入口是静态类的静态方法,Scala特有)

因为Scala中没有静态类和静态方法,但是Scala可以使用object声明静态类(单例类,java中bean交给工程或者静态成员变量,虚拟机只加载一次),该静态类的所有方法都是可以直接调用的,不需要new关键字(new关键字虚拟机会创建新的对象)

object JdbcUtil {
  def sayHello():Unit={
    println("你好!")
  }
}
var jdbcUtil1=JdbcUtil
var jdbcUtil2=JdbcUtil
println(jdbcUtil1)
println(jdbcUtil2)
println(jdbcUtil1==jdbcUtil2) //true
jdbcUtil1.sayHello()
JdbcUtil.sayHello()
Class类
  • 没有默认构造
class Animal {
  def sleep():Unit={
    println("sleep...")
  }
}
val a1=new Animal 
val a2=new Animal
val a3=new Animal()
println(a1==a2) //false

通过Class创建的类在创建对象的时候必须使用new关键字

  • 指定默认构造

    Scala默认构造不写,不用写括号

    Scala的默认构造必须写在类上,写完必须给默认构造提供参数

    class User(name:String) {//默认构造
      def sayHi():Unit={
        println(s"${name}")
      }
    }
    
    val user = new User("张三")
    user.sayHi()
    
  • 扩展默认构造(java是覆盖默认构造,添加有参构造无参构造就没了;Scala中的默认构造无法覆盖,一直存在)

class User(name:String) {//默认构造
    var age:Int= _

    def this(name:String,age:Int){  //扩展构造
        this(name) //代码第一行必须覆盖默认构造器
        this.age=age
    }

    def sayHi():Unit={
        println(s"${name},${age}")
    }
}

必须在扩展构造的第一行显示的默认构造的方法。扩展默认构造使用this关键字

构造方法 没有返回值

伴生对象

如果类和object在一个scala源文件中,则成为object User是Class User的伴生对象,伴生对象相较于其他对象有优先操作User的权限,比如可以使用伴生对象User快速创建Class User的对象:

没有new关键字时:

1、有()伴生,调用伴生对象的工厂方法(叫工厂方法是因为是静态的)

2、没有()永远是单例【我就纳闷这个单例是咋创建出来的,类加载的时候】

  • apply 工厂方法 创建类的对象

    class User(name:String){
       var age:Int=_
      def this(name:String,age:Int){
        this(name)
        this.age=age
      }
    }
    object User{
      def apply(name:String): User = new User(name)
      def apply(name: String,age:Int): User = new User(name,age)
    }
    
    var u1=new User("zs")   //创建
    var u2=new User("zs",18)// 创建
    var u3=User("zs")  //调用apply创建
    var u4=User("zs",18)//调用apply创建
    
    var u5=User //单例对象
    var u6=User //单例对象
    
    var u5=User
    var u6=User
    
  • unapply解码对象的属性

    class User(var name:String){
       var age:Int=_
      def this(name:String,age:Int){
        this(name)
        this.age=age
      }
    }
    object User{
        def unapply(user: User): Option[(String, Int)] = {
            if(user==null) {
                Some(("",0))
            }else{
                Some((user.name,user.age))
            }
        }
        def apply(name:String): User = new User(name)
        def apply(name: String,age:Int): User = new User(name,age)
    }
    
    val u=new User("张三1",18)
    val User(name:String,age:Int)=u
    println(s"${name},${age}")
    

scala中没有提供get set方法,要想取得对象的属性有两种方式

1、(low)普通变量变成成员变量 添加 var

2、(优雅)可以反序列化参数,只需提供unapply方法(反解 为了看懂源码)【提供unapply方法也要var,感觉可没必要哇】

抽象类(和java中一模一样)
abstract class Animal(name:String) {
  def eat():Unit={
    println(s"${name}会吃...")
  }
  def sleep():Unit
}

Java语法类型,可以有构造,但是无法创建对象。

特质Trait=java中的抽象类+接口(特有的性质)
trait Flyable {
  def fly():Unit//接口
}
trait Speekable {
    def speek():Unit={//方法
        println("鸟儿会飞")
    }
}

java8中接口中有默认方法实现

类似Java的接口,没有构造,可以有默认方法实现。

继承(和java一样类与类之间是单继承,接口之间多实现)
class Dog(name:String) extends Animal(name:String) with Speekable {
    override def sleep(): Unit = {
        println(s"${name} 睡觉")
    }

    override def eat(): Unit = {//覆盖父类中的方法
        println(s"${name} 啃骨头")
    }

    override def speek(): Unit = {
        println(s"${name}汪汪叫")
    }
}

继承抽象类,抽象类的接口必须实现,抽象类的方法可覆盖,可不覆盖

动态混入(scala特有)
class SmallBird(name:String) extends Animal (name:String){
  override def sleep(): Unit = {
    println(s"${name} 睡觉...")
  }
}
var smallBird=new SmallBird("小麻雀") with Flyable{
    override def fly(): Unit = {
        println("小麻雀会飞了")
    }
}
smallBird.sleep()
smallBird.fly()
强制混入(在接口中限定)

打比方 只要会飞的一定是动物(限制类型)

仅仅实现用extends

又继承又实现 extends + with

trait Flyable {
  this:Animal=> //必须在第一行 强制认定所有Flayable的子类,一定是Animal
  def fly():Unit={
    println(s"${name} 会飞")
  }
}

class Parrot(name:String)  extends Animal(name:String) with Flyable {
  override def sleep(): Unit = {
    println(s"${name}睡觉")
  }
}
val parrot = new Parrot("小鹦鹉")
parrot.fly()
self-type(自类型)

类里面写匿名内部类,匿名内部类为了避免this冲突,给自己起别名

class Pig(name:String) extends Animal(name:String){
  self=>  //等价  self:Pig=> 
  override def sleep(): Unit = {
    println(self == this)
    println(this.name+" 会睡!")
    println(self.name+" 会睡!")
  }
}

实际上是混入一种变体形式

case-class(加强版的tuple)

在scala中建模用tuple和样例类

样例类一般用作数据建模,因此样例类的属性都是只读(元组类似),样例类在使用的使用的时候无需使用new关键字,==比较的内容。

case class User(id:Int,name:String,sex:Boolean)
val u1=new User(1,"zs",true)
val u2=new User(1,"zs",true)
val u3=User(1,"zs",true)
println(u1)
println(u2)

注意样例类与类之间不允许出现继承关系。

样例类可以继承普通类

样例类没有子类

样例类之间可以实现快速拷贝

val u1=new User(1,"zs",true)
val u2=u1.copy(id=2)
println(u1)//User(1,zs,true)
println(u2)//User(2,zs,true)

7、函数式变量|对象

函数接口

在Java1.8中提出了一个Functional Interface,如果一个接口里面只能有一个抽象方法。这种类型的接口也称为SAM接口,即Single Abstract Method interfaces。将该接口成为函数式接口。

@FunctionalInterface
public interface IDemoService {
    public Integer sum(Integer x,Integer y);
}

@FunctionalInterface编译检查,确保该接口中只用一个抽象方法。

在1.8提出lambda表达式,用于表示这种函数式接口。

IDemoService demoService1=(Integer x, Integer y) -> x+y;
IDemoService demoService2=(x,y)->x+y;

和Java类似,Scala中也提供了类似于Java当中的Functional Interface,默认情况下,提供了Function022个函数式接口,所有的Scala的函数或者方法都是Function022的子类。可以使用 _将任意一个标准函数,转换为函数式变量。

scala> def sum(x:Int,y:Int): Int ={
     |     x+y
     |   }
sum: (x: Int, y: Int)Int

scala> val func=sum _
func: (Int, Int) => Int = <function2>

通常将func称为sum的函数的部分应用函数,通常使用部分应用函数表示一个函数对象。不难看出func字面量是一个<function2>

尝试以下测试

scala> func.isInstanceOf[Function2[Int,Int,Int]]
res2: Boolean = true

可以看出 得到的func确实是Function2的子类。既然func是Function2的子类,一定可以调用Function2的apply方法实现数据计算逻辑

scala> func.apply(1,2)
res3: Int = 3

scala> func(1,2)
res4: Int = 3

在Scala中Function0~Function22存在着变体写法(lambda写法):

scala> func.isInstanceOf[(Int,Int)=>Int]
res5: Boolean = true

也就意味着:(Int,Int)=>Int 等价 Function2[Int,Int,Int]

class SumFunc1 extends Function2[Int,Int,Int] {
  override def apply(v1: Int, v2: Int): Int = {
    v1+v2
  }
}
--- 
class SumFunc2 extends ((Int,Int) =>Int) {
  override def apply(v1: Int, v2: Int): Int = {
    v1+v2
  }
}

由于标准函数一般是无法作为参数单独传递,因此在Java中如果想要传递一个函数,必须将该函数封装称为一个函数式对象。

public static Integer process(IDemoService demoService,Integer x,Integer y){
    return demoService.sum(x,y);
}
Integer process = process((v1, v2) -> v1 + v2, 1, 2);
System.out.println(process);

可以看出使用Java做Lambda非常麻烦,因为所有lambda背后都必须有一个FunctionInterface

object TestScalaLanguage {
  def main(args: Array[String]): Unit = {
     println(process1((v1,v2)=>v1+v2,1,3))
     println(process2((v1,v2)=>v1*v2,1,3))
  }
  def process1(fun:Function2[Int,Int,Int],x:Int,y:Int):Int={
    fun(x,y)
  }
  def process2(fun:(Int,Int)=>Int,x:Int,y:Int):Int={
    fun(x,y)
  }
}
scala> Array(1,2,3).filter(i=>i%2!=0).map(i=>i*i)
res12: Array[Int] = Array(1, 9)
偏函数

偏函数主要适用于处理指定类型的参数数据,通常用于集合处理中。

val fun=new PartialFunction[Any,Int] {//只处理Int类型元素
    //需要处理的类型
    override def isDefinedAt(x: Any): Boolean = {
      println("isDefinedAt:"+x)
      x.isInstanceOf[Int]
    }
    //应用 函数处理数据
    override def apply(v1: Any): Int = {
      println("apply:"+v1)
       v1.asInstanceOf[Int]+1
    }
  }
val array = Array(1,2,"a",true,3,4,5)
array.collect(fun)
.foreach(item=>print(item+"\t"))

正常用法:

val a:Any=11
if(fun.isDefinedAt(a)){
    fun(a)
}

通常偏函数,还有另外一种写法,表示该偏函数,只处理Int类型的数据,如果数据不是Int,系统就抛出异常

val fun2:PartialFunction[Any,Int] = {case x:Int => x+1}
val array = Array(1,2,"a",true,3,4,5)
array.collect(fun2) //array.collect({case x:Int => x+1}) 
---
val a= for(i<- array;if(fun2.isDefinedAt(i))) yield fun2(i)

8、可见性(了解,因为Scala中不强调封装)

Scala 中的默认可见性为 public,所谓默认即你没有在类或者成员前显示加 private 或 protected 可见性关键字,默认都是public,虽然默认是public的但是scala中并没有public关键字,加上public编译报错。

class Student {
  var id:Int = _
  var name:String = _

  def this(id:Int,name:String){
    this()
    this.id = id
    this.name = name
  }
}
var stu = new Student(1,"zs")
println(s"${stu.id}")
private限定
  • private修饰的属性|方法

    只能被本类以及伴生对象可见,子类不可见

    class Student {
      private var id:Int = _
      private var name:String = _
    
      def this(id:Int,name:String){
        this()
        this.id = id
        this.name = name
      }
    }
    object Student{
      def unapply(student: Student): Option[(Int,String)] = {
        Some(student.id,student.name)
      }
    }
    
        var stu = new Student(1,"zs")
        var Student(id,name) = stu
        println(s"${id},${name}")
    

    Scala中private可以私有属性;也可以私有方法,私有方法只有伴生对象能拿到这方法,外界通过伴生对象工厂方法创建对象

    Scala并不推荐使用私有属性,同时提供公开方法

    一般通过伴生对象的unapply解码对象属性

  • private修饰类

    该类的所有成员属性对外皆不可见,包括伴生对象。一旦给一个class加上private修饰就直接将该类的默认构造全部隐藏

    • private修饰默认构造
    class Student private() {//这个()要不要都无所谓	修饰的是默认构造
      var id:Int = _
      var name:String = _
    
      def this(id:Int,name:String){//扩展构造
        this()
        this.id = id
        this.name = name
      }
      def sayHello():Unit={
         println("hello")
       }
    }
    object Student{
      def unapply(student: Student): Option[(Int,String)] = {
        Some(student.id,student.name)
      }
    
    //  def apply: Student = new Student()
    
      def apply(): Student = new Student()
      def apply(id:Int,name:String): Student = new Student(id,name)
    }
    
        //可以通过伴生对象调用各种方法
    	var stu =Student(1,"zs")
        var a = Student//单例	仅仅只是伴生对象
        var b = Student()//工厂创建
        var Student(id,name) = stu
        println(s"${id},${name}")
    
        println("a   "+a)
        println("b   "+b)
    
    
    1,zs
    a   com.baizhi.demo6.Student$@38082d64
    b   com.baizhi.demo6.Student@dfd3711
    

    以下写法,该Student对外不可见。同Java修饰内部类

    private class Student{//修饰的是类,一般用在内部类中
        //.....
    }
    
    class Master {//师傅
        private class Slave{ //徒弟
        }
        def teach():Unit={
           val slave = new Slave()
           println(slave)
        }
    }
    

protected 限定

  • 修饰属性|方法,

    可以被子类以及子类的伴生对象可见。

class Student {
  protected var id:Int=_
  protected var name:String =_
  
  protected def say():Unit={
    println(s"${name},${id}")
  }
}

class SmallStudent  extends  Student {
    def this(id:Int,name:String){
      this()
      this.id=id
      this.name=name
    }
}
  • 修饰类

该类只能被本包下的子类所继承,在继承的时候 并不继承父类的可见性

package com.baizhi.demo09

protected  class Student  { //只可以被本包子类继承,其它包下不可见
  protected var id:Int=_
  protected var name:String =_

  protected def say():Unit={
    println(s"${name},${id}")
  }
}
class SmallStudent  extends  Student {
    def this(id:Int,name:String){
      this()
      this.id=id
      this.name=name
    }

  override  def say(): Unit = { //默认情况下,子类再继续父类的方法时候,会继承方法的可见性,覆盖父类方法可见性
    println(s"${id},${name}")
  }
}

如果子类不覆盖父类的方法,在继承父类方法的时候,也会继承父类方法的可见性。

this限定

当被this限定修饰,该方法或者属性只能被本类内部可见,去除伴生对象。

class Animal {
  private|protected[this]  var  name:String=_ //去除伴生对象的可见性
  def this(name:String){
    this()
    this.name=name
  }
  def say():Unit={
    println(s"${name}")
  }
}

包限定

package com.baizhi.demo11

class Animal {
  private[demo11] def say():Unit={ //所有在demo11包下的类,都可看到 say方法,此时private限定失去了意义
     println("animal say")
   }
}

9、常见关键字

final 关键字

修饰类别JavaScala
最终类,没有子类最终类,没有子类
方法不能被覆盖不能被覆盖
属性常量,不允许修改属性不允许被子类遮盖(val属性)
class Animal {
  final val name:String="大黄"
  def say():Unit={
     println(s"${name}")
  }
}
---
class Dog extends  Animal {
   override  val name:String="小黑" //错误
}

√lazy关键字

被lazy修饰的val常量,只用被真正是使用的是时候,才会被初始化。

lazy val num=sum(1,2)
println(s"${num}")

def sum(x:Int,y:Int):Int={
    println("===========")
    x+y
}

sealed关键字

修饰一个类,被sealed修饰的类所已知子类,必须和父类放置在一个源文件中。

sealed class Message(content:String)
case class SmsMessage(content:String,phone:String) extends Message(content:String)
case class EmailMessage(content:String,email:String) extends Message(content:String)
val messages = Array[Message](SmsMessage("hello","110"),EmailMessage("你好","11@qq.com"))
messages.foreach(message=>{
    message match {
        case m:SmsMessage =>{
            println("收到短信:"+m.phone)
        }
        case m:EmailMessage=>{
            println("收到邮件:"+m.email)
        }
    }
})

10、隐式转换/注入/增强 - 重点

implicit 变量- 隐式值

一般定义隐式值的目的是为了隐式注入,一般要求同一个程序上下文只能一种类型隐式值

scala> implicit var a:Int=100
a: Int = 100

scala> var m=implicitly[Int]  //按照类型注入
m: Int = 100

implicit 修饰参数- 隐式

object MyImplicits {
  implicit var i= 100 //确保隐式值类型 只能有一个
}

object TestMyImplicits {
  def main(args: Array[String]): Unit = {
    import com.baizhi.demo12.MyImplicits._
    var num = implicitly[Int]	//那边用i了这边就不能用i否则会报错
    println(s"${num}")
  }
}

Error:(6, 23) could not find implicit value for parameter e: Int
    var i = implicitly[Int]
Error:(6, 23) not enough arguments for method implicitly: (implicit e: Int)Int.
Unspecified value parameter e.
    var i = implicitly[Int]
object MyImplicits {
	implicit val f=(x:Int,y:Int)=>x+y
}
object TestMyImplicits {
  def main(args: Array[String]): Unit = {    
    import com.baizhi.demo13.MyImplicits._
    var result2=process(1,2)
    println(s"${result2}")
  }    
}
def process(x:Int,y:Int)(implicit fun:(Int,Int)=>Int):Int={
    fun(x,y)
}

implicit 修饰方法- 隐式转换 不兼容变成兼容

def tellTime(date:Date):Unit={
    println(s"${date.toLocaleString}")
}
import com.baizhi.demo13.MyImplicits._
tellTime("2019-9-20 16:34:50") // 等价 tellTime(str2Date("2019-9-20 16:34:50")) 
//tellTime(new Date())
object MyImplicits {
  implicit def str2Date(str:String):Date={//参数表示要转换的类型,返回值表示需要的目标类型
    val sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    sdf.parse(str)
  }
}

implicit 修饰类- 隐式增强 不可能变可能

class Pig {
    def sleep():Unit={
      println("sleep")
    }
    def eat():Unit={
      println("eat")
    }
}
object MyImplicits {
  implicit class PigImplicits(pig:Pig){
    def fly():Unit={
        
      println("pig 会飞")
    }
  }
}
import com.baizhi.demo13.MyImplicits._
val pig = new Pig()
pig.eat()
pig.sleep()
pig.fly()//增强方法

Scala泛型(看懂)

<: 上界限定

就是	<=
要求 T 必须是指定泛型或者指定泛型的子类

  def keep[T<:Dog](t:T):Unit={
    println(t)
  }
  keep(new SmallDog(""))//给参数定义个泛型

>: 下界限定

>=(有点bug 把小狗当做狗了 给小狗加上小狗的泛型就可以了)
原意是表示 T 必须是指定泛型或者指定泛型的父类

  def keep[T>:Dog](t:T):Unit={
    println(t)
  }
    keep(new Animal)//给参数定义个泛型

<% 视图限定

强制将T看做成SmallDog,但是要求用户在使用时必须提供隐式转换,将T转换为SmallDog
class SmallDog(name:String)  extends Dog {
    def speek():Unit={
        println(s"${name} 汪汪叫~")
    }
}

------
implicit def str2SmallDog(str:String):SmallDog={
    new SmallDog(str)
}
playWithSmallDog("小狗")

def playWithSmallDog[T<% SmallDog](dog:T):Unit={
    dog.speek()
}

A: T上下文限定

和视图限定相似但是不同
表示上下文中一定会有一个T隐式值
先画大饼
    def compare[T:MyOrder](t1:T,t2:T):Unit={
      val myOrder = implicitly[MyOrder[T]]
      myOrder.compareT(t1,t2)
    }
    implicit val myOrder = new MyOrder[String]
    compare("a","b")


------
class MyOrder[T] {
  def compareT(t1: T,t2:T):Unit={
    println(t1+" "+t2)
  }
}

+A 协变

可以把小给大
即:将小泛型的引用赋值给大泛型的引用
class DogKeeper[+T] {}
var dogKeeper1=new DogKeeper[SmallDog]
var dogKeeper2=new DogKeeper[Dog]
var dogKeeper3=new DogKeeper[Animal]

dogKeeper3=dogKeeper2
dogKeeper2=dogKeeper1

-A 逆变

可以把大给小
即:将大泛型的引用赋值给小泛型的引用

A 不变(java 中没有协变和逆变,只有不变;java中泛型不支持多态)

指定将相同泛型的引用赋值给相同泛型的引用
class DogKeeper[-T] {}
var dogKeeper1=new DogKeeper[SmallDog]
var dogKeeper2=new DogKeeper[Dog]
var dogKeeper3=new DogKeeper[Animal]

dogKeeper2=dogKeeper3
dogKeeper1=dogKeeper2

(重点)集合/数组 操作

Array
scala>  var array=Array(1,2,3,4,5)
array: Array[Int] = Array(1, 2, 3, 4, 5)
scala> array(0)= -1
scala> array(0)
res2: Int = -1
scala> array.length
res4: Int = 5
scala> array.size
res5: Int = 5
Range
scala> var range =new Range(0,10,2)
range: scala.collection.immutable.Range = Range(0, 2, 4, 6, 8)

scala> var range= 0 to 10 by 2
range: scala.collection.immutable.Range = Range(0, 2, 4, 6, 8, 10)

scala> var range= 0 until 10 by 2
range: scala.collection.immutable.Range = Range(0, 2, 4, 6, 8)
Vector
scala> var vec=Vector(0,10,1)
vec: scala.collection.immutable.Vector[Int] = Vector(0, 10, 1)

scala> vec(1)
res12: Int = 10

scala> vec(2)
res13: Int = 1

scala> for(i<- 0  to 10 by 2) yield i
res15: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 2, 4, 6, 8, 10)
  • Iterator
scala> var it=Iterator(1,2,3)
it: Iterator[Int] = non-empty iterator

scala> for(i<- it) println(i)
1
2
3

scala> for(i<- it) println(i)

scala> var it=Iterator(1,2,3)
it: Iterator[Int] = non-empty iterator

scala> it.size
res21: Int = 3

scala> it.size
res22: Int = 0
  • List (只读)
scala> val list = List(1,2,3,4,5)
list: List[Int] = List(1, 2, 3, 4, 5)

scala>     list.size
res0: Int = 5

scala>

scala>     list.+:(-1) //返回新的List,原始数据不变
res1: List[Int] = List(-1, 1, 2, 3, 4, 5)

scala>     list.::(-1) //追加元素
res2: List[Int] = List(-1, 1, 2, 3, 4, 5)

scala>

scala>     list.++(List(0,0)) //向后追加,元素
res3: List[Int] = List(1, 2, 3, 4, 5, 0, 0)

scala>     list.++:(List(0,0))//向前追加,元素
res4: List[Int] = List(0, 0, 1, 2, 3, 4, 5)

scala>     list.:::(List(1,3)) //向前追加 元素
res5: List[Int] = List(1, 3, 1, 2, 3, 4, 5)

scala>

ListBuffer(支持修改)

scala> var listBuffer=new ListBuffer[Int]
listBuffer: scala.collection.mutable.ListBuffer[Int] = ListBuffer()

scala>     listBuffer.+=(1)//添加元素
res22: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1)

scala>     listBuffer.update(0,-1)//修改0位置为-1

scala>     listBuffer.-=(-1)//删除元素
res24: scala.collection.mutable.ListBuffer[Int] = ListBuffer()

scala> listBuffer.++=(Array(1,2,3,4))
res25: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4)

scala> listBuffer.remove(1)
res26: Int = 2

scala> listBuffer
res27: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 3, 4)

Set(不可变)

scala> var set=Set(1,2,3,4,5,1)
set: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)

scala>     set.+(-1)
res35: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, -1, 4)

scala>     set.size
res36: Int = 5

scala>     set.+=(10)
scala> set
res38: scala.collection.immutable.Set[Int] = Set(5, 10, 1, 2, 3, 4)

Set(可变集合)

scala>  var set=scala.collection.mutable.Set(1,2,3,4,5,1)
set: scala.collection.mutable.Set[Int] = Set(1, 5, 2, 3, 4)

scala>     set.+(-1)
res51: scala.collection.mutable.Set[Int] = Set(1, 5, 2, -1, 3, 4)

scala>     set.size
res52: Int = 5

scala>     set.+=(10) //添加元素,修改自己
res53: scala.collection.mutable.Set[Int] = Set(1, 5, 2, 3, 10, 4)

scala>     println(set.add(1)) //表示添加是否成功
false
scala>     set.remove(1)
res55: Boolean = true
  • HashMap(不可变)
import scala.collection.mutable.HashMap

var hm=HashMap[String,String](("001","zhangsan"),("002","李四"))
//val hm1=Map[String,String](("001","张三"),("002","lisi"))
hm.-("001") //删除key,不修改原始值
hm.+(("003","王五")) //添加值,不修改原始值
//获取Map的值
val value = hm.get("004").getOrElse("没有值")

//迭代key
for(k<-hm.keys){
    println(hm.get(k).getOrElse(""))
}
val size = hm.size
//迭代值
for(i<-hm.values) println(i)
  • HashMap(可变)
var hm=HashMap[String,String](("001","zhangsan"),("002","李四"))
//val hm1=Map[String,String](("001","张三"),("002","lisi"))
hm.-("001") //删除key,不修改原始值
hm.+(("003","王五")) //添加值,不修改原始值
hm.put("004","赵六")
hm.remove("004")
//获取Map的值
val value = hm.get("004").getOrElse("没有值")
//迭代key
for(k<-hm.keys){
    println(hm.get(k).getOrElse(""))
}
val size = hm.size
//迭代值
for(i<-hm.values) println(i)

集合计算(必须掌握)

为何要学习Scala集合计算?

在这里插入图片描述

算子学习

参考:https://blog.csdn.net/weixin_38231448/article/details/89354185

√ filter算子

用于对集合数据List[T]做过滤,需要传递一个 fn: T => Boolean

scala> List(1,2,3,4,5).filter(item => item %2 ==0) //List(1,2,3,4,5).filter(_ % 2 ==0)
res11: List[Int] = List(2, 4)

scala> val list=List("hello ni hao","hello world","hello scala")
list: List[String] = List(hello ni hao, hello world, hello scala)

scala> list.filter(item=> item.contains("scala"))// list.filter(_.contains("scala"))
res13: List[String] = List(hello scala)

还有一个filterNot算子和filter相反,将满足条件的元素去除。

scala> List(1,2,3,4,5).filterNot(_ % 2 ==0)
res19: List[Int] = List(1, 3, 5)
flatten

用作数组数据降维,例如List[Array[T]] 通过flatten转换可以得到List[T]

scala> val list=List(Array(1,2,3),Array(4,5))
list: List[Array[Int]] = List(Array(1, 2, 3), Array(4, 5))

scala> list.flatten
res21: List[Int] = List(1, 2, 3, 4, 5)
√ map算子

用作数组元素的转换List[T]集合需要提供 fun:T=>U将List[T]转换为List[U]

scala> List("a","b","c").map(item=> (item,1))
res22: List[(String, Int)] = List((a,1), (b,1), (c,1))

scala> val words=List("this is a demo","hello scala").map(line=>line.split(" ")).flatten
words: List[String] = List(this, is, a, demo, hello, scala)
scala> words.map(word=>(word,1))
res27: List[(String, Int)] = List((this,1), (is,1), (a,1), (demo,1), (hello,1),
(scala,1))
√flatMap等价 1.map 2. flatten

专门用于将集合中的元素先进行map转换 List[T] ,尝试将元素T转换为List[U],一般需要提供fun: T =>List[U],这样原始的List[T]就变成List[List[U]],然后该算子会执行flatten将List[List[U]]展开成为List[U]

scala> val lines=List("this is a demo","hello scala")
lines: List[String] = List(this is a demo, hello scala)

scala> val words=lines.flatMap(line=>line.split(" "))
words: List[String] = List(this, is, a, demo, hello, scala)


scala> val linesplits=lines.map(line=> line.split(" "))
linesplits: List[Array[String]] = List(Array(this, is, a, demo), Array(hello, sc
ala))

scala> linesplits.flatten
res36: List[String] = List(this, is, a, demo, hello, scala)

√sort算子

sorted

scala> val nums = List(2,3,5,1,4,6)
nums: List[Int] = List(2, 3, 5, 1, 4, 6)

scala> nums.sorted
res37: List[Int] = List(1, 2, 3, 4, 5, 6)

scala>  nums.sorted(new Ordering[Int]{
     |       override def compare(x: Int, y: Int): Int = {
     |         (x-y) * -1
     |       }
     |     })
res39: List[Int] = List(6, 5, 4, 3, 2, 1)

sortBy(根据某个字段排序)

scala> var users=List((1,"zs",18),(2,"lisi",20))
users: List[(Int, String, Int)] = List((1,zs,18), (2,lisi,20))

scala> users.sortBy(user=>user._3)
res41: List[(Int, String, Int)] = List((1,zs,18), (2,lisi,20))

scala> users.sortBy(user=>user._3)(new Ordering[Int]{
     |       override def compare(x: Int, y: Int): Int = {
     |         (x-y) * -1
     |       }
     |     })
res42: List[(Int, String, Int)] = List((2,lisi,20), (1,zs,18))

sortWith(感觉比sortBy好使)

scala> var users=List((1,"zs",18),(2,"lisi",20))
users: List[(Int, String, Int)] = List((1,zs,18), (2,lisi,20))

scala> users.sortWith((u1,u2)=> u1._3 > u2._3)
res45: List[(Int, String, Int)] = List((2,lisi,20), (1,zs,18))

scala> users.sortWith((u1,u2)=> u1._3 < u2._3)
res46: List[(Int, String, Int)] = List((1,zs,18), (2,lisi,20))
√groupBy
scala> val list=List("a","b","a","b","c")
list: List[String] = List(a, b, a, b, c)

scala> list.groupBy(c=>c)
res47: scala.collection.immutable.Map[String,List[String]] = Map(b -> List(b, b)
, a -> List(a, a), c -> List(c))

有如下数组:List(“this is a demo”,"good good study ",“day day up”,"come on baby "),请输出格式数据

List((this,1),(good,2),…)

scala> val lines=List("this is a demo","good good study ","day day up","come on
baby")

scala> val wordpair=lines.flatMap(line=>line.split(" ")).map(word=>(word,1))
wordpair: List[(String, Int)] = List((this,1), (is,1), (a,1), (demo,1), (good,1)
, (good,1), (study,1), (day,1), (day,1), (up,1), (come,1), (on,1), (baby,1))

scala> val group=wordpair.groupBy(word=>word._1).toList
group: List[(String, List[(String, Int)])] = List((this,List((this,1))), (demo,L
ist((demo,1))), (is,List((is,1))), (good,List((good,1), (good,1))), (up,List((up
,1))), (a,List((a,1))), (come,List((come,1))), (on,List((on,1))), (baby,List((ba
by,1))), (day,List((day,1), (day,1))), (study,List((study,1))))                                                             
scala> group.map(t=>(t._1,t._2.size))
res53: List[(String, Int)] = List((this,1), (demo,1), (is,1), (good,2), (up,1),
(a,1), (come,1), (on,1), (baby,1), (day,2), (study,1))

sum

只能针对数值类型的数组做计算

scala> List(1,2,4,5).sum
res57: Int = 12
count

计算数组中数据的个数

scala> List("a","c","c").count(item=>true)
res63: Int = 3
max|min|maxBy|minBy
scala> List(1,3,4,5,6).max
res65: Int = 6

scala> List(1,3,4,5,6).min
res66: Int = 1

scala> List(("a",1),("a",2),("c",3)).maxBy(t=>t._2)
res68: (String, Int) = (c,3)

scala> List(("a",1),("a",2),("c",3)).maxBy(t=>t._1)
res69: (String, Int) = (c,3)

scala> List(("a",1),("a",2),("c",3)).minBy(t=>t._2)
res70: (String, Int) = (a,1)
√reduce

在这里插入图片描述

scala> List(1,2,3,4).reduce((v1,v2)=> v1+v2)//scala> List(1,2,3,4).reduce(_+_)
res71: Int = 10

√aggregate

在这里插入图片描述

scala> val ints = List(1,2,3,4,5,6)
ints: List[Int] = List(1, 2, 3, 4, 5, 6)

scala> val tuple = ints.aggregate((0.0,0))((z,v)=>(z._1+v,z._2 +1),(b1,b2)=>
(b1._1+b2._1,b1._2+b2._2))
tuple: (Double, Int) = (21.0,6)

scala> var avg=tuple._1/tuple._2
avg: Double = 3.5
√fold

在这里插入图片描述

scala> val ints = List[Int]()
ints: List[Int] = List()

scala> ints.fold(0)((v1,v2)=>v1+v2)
res2: Int = 0

scala> val ints = List[Int](1,2,3,4)
ints: List[Int] = List(1, 2, 3, 4)

scala> ints.fold(0)((v1,v2)=>v1+v2)
res4: Int = 10
字符统计
scala> var arrs=Array("this is a demo","good good study","day day up")
arrs: Array[String] = Array(this is a demo, good good study, day day up)

scala> arrs.flatMap(line=>line.split(" "))
		   .groupBy(word=>word).toList
           .map(t=>(t._1,t._2.size))
           .sortBy(t=>t._2)

res18: List[(String, Int)] = List((this,1), (demo,1), (is,1), (up,1), (a,1), (st
udy,1), (good,2), (day,2))


scala> arrs.flatMap(line=>line.split(" "))
			.map((_,1))
			.groupBy(t=>t._1)
			.toList.map(t=>(t._1,t._2.map(_._2).sum))
			.sortBy(t=>t._2)

res19: List[(String, Int)] = List((this,1), (demo,1), (is,1), (up,1), (a,1), (st
udy,1), (good,2), (day,2))
count

计算数组中数据的个数

scala> List("a","c","c").count(item=>true)
res63: Int = 3
max|min|maxBy|minBy
scala> List(1,3,4,5,6).max
res65: Int = 6

scala> List(1,3,4,5,6).min
res66: Int = 1

scala> List(("a",1),("a",2),("c",3)).maxBy(t=>t._2)
res68: (String, Int) = (c,3)

scala> List(("a",1),("a",2),("c",3)).maxBy(t=>t._1)
res69: (String, Int) = (c,3)

scala> List(("a",1),("a",2),("c",3)).minBy(t=>t._2)
res70: (String, Int) = (a,1)
√reduce

[外链图片转存中…(img-EMPPPNhU-1571672994569)]

scala> List(1,2,3,4).reduce((v1,v2)=> v1+v2)//scala> List(1,2,3,4).reduce(_+_)
res71: Int = 10

√aggregate

[外链图片转存中…(img-ytbD98oo-1571672994570)]

scala> val ints = List(1,2,3,4,5,6)
ints: List[Int] = List(1, 2, 3, 4, 5, 6)

scala> val tuple = ints.aggregate((0.0,0))((z,v)=>(z._1+v,z._2 +1),(b1,b2)=>
(b1._1+b2._1,b1._2+b2._2))
tuple: (Double, Int) = (21.0,6)

scala> var avg=tuple._1/tuple._2
avg: Double = 3.5
√fold

[外链图片转存中…(img-yhWz4yci-1571672994570)]

scala> val ints = List[Int]()
ints: List[Int] = List()

scala> ints.fold(0)((v1,v2)=>v1+v2)
res2: Int = 0

scala> val ints = List[Int](1,2,3,4)
ints: List[Int] = List(1, 2, 3, 4)

scala> ints.fold(0)((v1,v2)=>v1+v2)
res4: Int = 10
字符统计
scala> var arrs=Array("this is a demo","good good study","day day up")
arrs: Array[String] = Array(this is a demo, good good study, day day up)

scala> arrs.flatMap(line=>line.split(" "))
		   .groupBy(word=>word).toList
           .map(t=>(t._1,t._2.size))
           .sortBy(t=>t._2)

res18: List[(String, Int)] = List((this,1), (demo,1), (is,1), (up,1), (a,1), (st
udy,1), (good,2), (day,2))


scala> arrs.flatMap(line=>line.split(" "))
			.map((_,1))
			.groupBy(t=>t._1)
			.toList.map(t=>(t._1,t._2.map(_._2).sum))
			.sortBy(t=>t._2)

res19: List[(String, Int)] = List((this,1), (demo,1), (is,1), (up,1), (a,1), (st
udy,1), (good,2), (day,2))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值