Scala基础

Scala基础教程:http://www.runoob.com/scala/scala-tutorial.html

值与变量(推荐使用val,第一选择使用val,如果业务需要,才允许使用var)
  val和var的区别?
  val: 值,赋值后,数据不可变
  var: 变量,赋值后,数据可变
  定义格式:
    [var or val] name[:type] = [表达式(用大括号括起来的可以当做表达式)或者值/对象或者下划线]
下划线会给个默认值。


Scala表达式的返回值就是最后一行代码的执行结果,但是scala保留了return的含义,但是不推荐使用。
Unit: 类似java中的void,表示返回空类型

懒加载: lazy,指变量在第一次进行使用的时候进行初始化操作, 而且只有在第一次调用的时候会进行初始化
lazy val c = {
  println("nihao")
  12 + 3
}

Scala中默认一行一条语句,不需要使用分号";"进行代码的格式化操作, 针对跨行的语句,会自动进行推断,但是要求能够进行推断出来
lazy val c = {
  val str = "yushu" +
       "gerry"
  println(str)
  println("nihao")
  12 + 3
}

String类型变量的写法:
  val str = "hadoop spark"
  val str = "hadoop spark \"mllib\""    转义双引号
  val str = """hadoop spark "mllib""""   保留三个双引号中的所以引号
  val str = """
    hadoop spark "mllib"
    spark core
    """
  val str = """
    |hadoop spark "mllib"
    |spark core
    |""".stripMargin

Scala的操作符:
  基本和Java一样,操作符的优先级基本和java一样
  特殊:
    1. 不支持一元操作符中的++和--
    2. 不支持三元/目操作符:(?:)
    3. Scala中的所有操作符实质上就是函数,函数也可以写成操作符
      所有以字母开头的操作符(函数)的优先级只比赋值操作符高
    4. 基本上所有的操作符都是左连接的,但是如果函数是以冒号(:)开头的,操作符是右连接的
    5. map进行循环的时候,可以匹配key/value,省略key/value的值的时候
==========Scala 判断 循环函数==================
IF-ELSE
  语法和Java一样,可以替换三目操作符的功能
  
Scala不支持break和continue关键字,但是可以同Breaks类实现类似break的功能

While、Do-While
  语法和Java一样
For
  Scala不支持Java的for循环写法
  for(item <- arr) {
  ....
  }
============================================
===============Scala函数=====================

  函数是一等公民 ====> 可以独立存在,可以赋值给任何变量、可以出现任何地方(类中、对象中、函数中....)
scala> def max(x: Int, y: Int): Int = {
     |     if (x > y)
     |       x
     |     else
     |       y
     |   }
max: (x: Int, y: Int)Int
  max:(Int, Int) =>  Int
     表示输入参数列表为:(Int,Int),返回结果类型为:Int
  函数的表示方式:f:T=>R, 一个函数f,输入参数为T,返回结果为R
  
如果一个函数在定义的时候,没有输入参数,可以给定空的参数列表也可以不给定(是否给定小括号), 如果一个函数的调用对于对象没有影响的情况下,可以选择不给定括号;但是当有影响的时候,也就是会改变对象的值的时候,一般建议给定小括号。
   调用函数的时候是否给定括号和定义函数的时候一致即可
  
匿名函数
  val max1 = max _
  max1(4,5)
  val max2 = (x: Int, y: Int) => {
    if (x > y)
      x
    else
      y
  }
  max2(4,5)
  匿名函数:没有函数名称的函数,一般情况会将匿名函数赋值给一个变量来使用
    (x: Int, y: Int) => {
      if (x > y)
        x
      else
        y
    }
  
函数的调用过程中,默认情况是从左往右匹配参数列表,但是可以在调用的时候,强制给定参数列表的值
scala> max(4,5)
res33: Int = 5

scala> max(x = 4, y =5)
res34: Int = 5

scala> max(y = 5, x = 4)
res36: Int = 5
  
高阶函数
   如果函数f有一个参数g,g是函数类型的,那么f就叫做高阶函数;
   接收其他函数作为参数的函数,被称作高阶函数。
   eg:
def f(g: T => R) {
  // 代码
}
    // 1. 可以不写数据类型,scala编译器会自动推断数据类型,根据定义的函数来进行推断
    greeting("gerry", (name) => println(s"${name}, Hi"))
    opera(1, 2, (a, b) => a + b)
    // 2. 如果输入参数只有一个的情况下,可以省略小括号
    greeting("gerry", name => println(s"${name}, Hi"))
    // 3. 如果左侧的输入参数在右侧的代码体中都使用了,而且使用顺序和参数列表中的顺序一致,并且所有参数仅仅使用一次,那么可以使用下划线代替,输入参数列表就不用写了(要求使用下划线代替后没有异议)
    greeting("gerry", println(_))
    opera(1, 2, _ + _)
    // 4. 如果右侧的函数体仅仅是调用其它已经存在的函数,而且传入的参数是所有左侧输入的参数列表中的参数,而且顺序一致,那么可以直接省略下划线
    greeting("gerry", println)  
  
===================Scala的常用高阶函数=============
map: 对传入的每个元素都进行映射,返回一个处理后的元素   Array(1, 2, 3, 4, 5).map(2 * _)
foreach: 对传入的每个元素都进行处理,但是没有返回值   (1 to 9).map("*" * _).foreach(println _)
filter: 对传入的每个元素都进行条件判断,如果对元素返回true,则保留该元素,否则过滤掉该元素   (1 to 20).filter(_ % 2 == 0)
reduceLeft: 从左侧元素开始,进行reduce操作,即先对元素1和元素2进行处理,然后将结果与元素3处理,
再将结果与元素4处理,依次类推,即为reduce;reduce操作必须掌握!spark编程的重点!!!
// 下面这个操作就相当于1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9
(1 to 9).reduceLeft( _ * _)
====================递归==========================
 在函数内部调用函数自身进行解决问题
  每一次递归会将允许代码添加到栈中,如果递归的深度太深的话,有可能出现OOM的异常
尾递归:对递归的一种优化方式,不会将每次的递归放到栈中
  要求:最后返回的实递归代码

def f(n:Int):Int = {
  if (n <= 1) 1
  else f(n - 1) * n
}

def f(n:Int, m:Int = 1):Int = {
  if (n <= 1) n * m
  else f(n - 1, m * n)
}
  
def f(n:Int):Int = {
  if (n <= 1) throw new RuntimeException("1")
  else f(n - 1) * n
}


def f(n:Int, m:Int = 1):Int = {
  if (n <= 1) throw new RuntimeException("1")
  else f(n - 1, m * n)
}
  
=====================================================  
集合中:优选选择使用不可变集合,业务需要才允许使用可变集合

数组
    变长数组(ArrayBuffer)和数组(Array)
    变长数组可以更改数组的大小(新增、删除数据、查、更改数据)
    数组不支持数组大小的更改(查、更改数据)
  数组下标从0开始,不能越界,如果访问下标异常的数据会抛出异常<ArrayIndexOutOfBoundsException>,使用小括号 + 下标的方式进行数据的获取,eg: arr(0) 获取下标为0的数组中的数据
  
数组 是集合中的一种数据类型,而元组不是集合中的类型 
  
元组:
   内部可以放不同数据类型的数据
   下标从1开始,读取数据方式为:下划线+下标,eg: tuple._1表示获取第一个元素的数据
   元组中的数据不允许进行修改操作,不允许修改元组的数据引用,至于数据内部是可以进行修改   
   元组中的数据类型可以是任何数据类型
   注意:Scala中最多支持22元组
   注意:可以通过函数->来创建一个二元组:    (a,b) <==等价于==> a -> b
  
List
  空链表: Nil
  重点注意:List的相关API  
  
Set:
  无序不重复的集合

Map:
  关联数组(key/value键值对的集合)
  存储的数据是Key:Value键值对
  Map中存储的数据可以看做是一个一个的二元组

集合注意事项:
  -1. 集合分为可变集合和不可变集合
  -2. 优先选择不可变集合使用
  -3. 默认集合就是不可变集合
  -4. 集合的相关的API
  
==============================================
Scala面向对象
  作用域:可以放在属性、方法、class、object、trait上
    public:默认,而且public不能写
    protected:功能和java一样,但是scala不推荐使用
    private: 功能和java一样
    private[包名/this]: 分别表示包可用、当前类对象可用
    
  class:类
    类似于java中的类(单继承等等)
  abstract class: 抽象类
    类似于java中的抽象类
  object:对象
    
   scala中不支持static关键字 类似于java中单例对象,在jvm中只存在一份;所以object中的所有属性、方法均可以看成是staitc关键字修饰的
  trait: 特质 
   当做接口来使用,但和Java的接口又有不同,这边可以有具体的方法实现

Scala中的类的继承是单继承的和java一样,构造的顺序和java一样   
class的构造函数
  默认构造函数为空
  主构造函数是class类名后定义的一个括号 + class的{}中的所有内容
  辅助构造函数是以this为名称的,而且没有返回值的方法/函数, 辅助构造函数必须调用主构造函数,而且必须是第一行
注意:将函数赋值给变量时,必须在函数后面加上空格和下划线

==============================================
object:
  对象,为了解决scala中不能class中写static的问题的一方案
  在jvm中只会存在一份,可以当做单例对象来使用
  内部可以定义属性、方法等

伴生对象/伴生类:
  当在一个文件中,class的名称和object的名称一致的时候,认为class是object的伴生类,object是class的伴生对象
  伴生类和伴生对象之间可以互相访问private修饰的变量/属性/方法
  
apply方法:
  object中:
    提供了一种便捷的对象构建方式,可以通过object名称以及apply函数的参数列表直接进行对象的构建,不需要使用new关键字
  class中:
    提供的是一种便捷的数据获取/判断操作,类似list(0)

update方法:
  class中:
    提供的一种数据插入、更新的便捷操作,类似arr(0) = 100
    
==============================================
case class:
  其实就是class和object的一个结合,内部会自动的生成class对应的object对象,并且在object中产生apply方法
  默认的属性是val修饰,可以改为var修饰
  注意:case class定义的时候,属性最多22个
  最常用的一个地方是:模式匹配

==============================================
trait
  当做Java的接口来使用
  区别:
    1. 可以包含已经实现的方法或者属性
    2. 一个类可以继承/实现多个trait

继承:
  Scala中的类是单继承的
  Trait是可以多继承的
  使用关键字extends进行class/trait的继承,多继承的时候使用关键字with
======================================================
泛型
  基本和java类型,java使用<>来表示泛型,scala中使用[]来表示泛型
  泛型可以出现在:类、object、方法、特质等上面
class Student[T]
def add[T](t:T)

 上下界:
    [A1 >: A]: 表示A是A1的下界,也就是A是A1的子类
    [A1 :< A]: 表示A是A1的上界,也就是A是A1的父类
  协变/逆变:
    [+T]: 协变, 如果有一个类C定义为C[+T], 同时A是B的子类,那么C[A]也就是C[B]的子类
    [-T]:逆变

class Person
class Teacher extends Person
  val t:Teacher = new Teacher()
  val p:Person = t

class Queue[T]
  var q1:Queue[Teacher] = new Queue[Teacher]()
  var q2:Queue[Person] = new Queue[Person]()
  q1 = q2 // 报错
  q2 = q1 // 报错
class Queue[+T]
  var q1:Queue[Teacher] = new Queue[Teacher]()
  var q2:Queue[Person] = new Queue[Person]()
  q1 = q2 // 报错
  q2 = q1 // 正常
class Queue[-T]
  var q1:Queue[Teacher] = new Queue[Teacher]()
  var q2:Queue[Person] = new Queue[Person]()
  q1 = q2 // 正常
  q2 = q1 // 报错
  
===================================================



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值