Fork me on GitHub

scala基础

类型

1.基本类型

和Java类似,scala也有基本类型,但是scala的基本类型也是对象,String类型是直接引用的Java的string,举个栗子(scala脚本):

scala> val num = 2 + 3
num: Int = 5

//等价于
scala> val num = (2).+(3)
num: Int = 5

基本操作符都是方法,定义在scala.基本类型里面,比如+ - * / ,也有一些稍微复杂的操作定义在富包装类中,以‘Rich+基本类型定义’,比如max min等

可变和不可变对象

函数式语言强调对象不可变,方法无副作用。

用val定义不可变对象,不可变对象初始化值时需要赋初值。

用var定义可变对象,可随时赋值

类型推演

三目运算符

Java:a > b ?a : b

scala: if(a>b) a else b

控制结构

for循环生成器

java: for(int i=1; i<=5; i++)

scala:for(i <- 1 to 5 by 1)

for守卫表达式

java: for(int i=1; i<=5 && i%2 == 0; i++)

scala: for(i <- i to 5 by 1 if i%2 == 0)

for推导式

var arr = for(i <- 1 to 5 by 1 if (i%2) == 0) yield{ println(i); i}

异常

java:

try{} 
catch(NullPointerException e1){}
catch(FileNotFoundException e2){}
finally{}

scala:

try{} 
catch{
	case e1:NullPointerException => {}
	case e2:FileNotFoundException => {}
	} 
finally{}

break and continue

import util.control.Breaks._

var arr = Array(1,3,9,5)
    breakable {
      for (i <- arr)
        if (i > 5) break
        else println(i)
    }
    
    println("continue...")
    //continue语句
    for (i <- arr)
      breakable{
        if (i> 5) break
        else println(i)
      }

模式匹配

1.Java的switch case语句,同时也支持守卫,和for循环类似

var num = 10;
    num match {
      case _ if(num % 2 == 0) => println("偶数")
      case _ if(num %2 != 0) => println("奇数")
      case _ => println("default")
    }

2.case类
case类是经过优化的类,会自动重载很多有用的方法比如:toString、equals、hashcode ,更重要的是,case类会自动生成伴生对象(object classname;apply方法)

数据结构

数组

//定义
var arr = Array(1,2,3)
var arr = new Array[Int](3)
//赋值
arr(0) = 12
//二维数组
var arr = Array.ofDim[Int](3,4)
arr(0)(1) = 10

元组

不同类型的数据的集合

val tuple = ("learn scala",56.2)
println(tuple._1+":"+tuple._2)

容器

可变容器和不可变容器.常见的List、Vector是不可变容器,Map、Set等既有可变的,也有不可变得

import scala.collection.immutable._
import scala.collection.mutable._

序列

List的定义和使用

//list1和list2的内容不可变
var list1 = List(1,2,3)
//Nil是一个空链表,list2=List(4,5,6)
var list2 = 4::5::6::Nil
var list3 = 7::8::list1

Vector

var vector = Vector(3, 4)
//向前添加
println(1 +: 2 +: vector)
//向后添加
println(vector :+ 5 :+ 6)

Range

Range是一种带索引的不可变等差数列,上面的1 to 5 by 1就是一个Range对象

包含起点,不包含终点的range:1 until 5 by 1

Set和Map

Set:var set = Set("Apache","Hadoop","Spark")

Map:var map = Map(1->"first",2->"Second")

迭代器

类和方法

方法

定义方式:def 方法名(参数名:参数类型, 参数名:参数类型,......):返回值类型 = {方法体}

简写方式:

  1. 无参数可以不加方法名后面的括号;
  2. 返回值类型也可以不写,通过推演得出;
  3. 方法体如果只有一句话,也可以不写花括号;
  4. 最后的返回值可以不写return关键字。
  5. 在类中定义的方法,可以使用中缀表示法简写

比如:def print = println("Hello Wolrd")

类的定义:
和Java类似的定义类的方式

访问权限:public(默认访问方式)、private、protected。当属性为private访问属性时,一般都会提供get和set方法,scala的getter和setter定义方式如下

class Person(var name:String){
  private var _age = 0
  def age = _age
  def age_=(a:Int) = _age = a
}

构造器

定义主构造器:class 类名(var|val 属性名:类型......)
定义在主构造器的和在类内部声明为public访问权限的属性都默认提供了getter和setter方法,以对象名.属性名的方式访问
例如

scala> class Counter(var count:Int)
defined class Counter
scala> var counter = new Counter(10)
counter: Counter = Counter@435a2c7d
//访问
scala> println(counter.count)
10

定义辅助构造器:def this(参数列表){}

第一个辅助构造器必须依赖主构造器,第二个辅助构造器必须依赖于第一个辅助构造器,以此类推。例如:

class Person() {
  private var _age = 0
  private var _name = ""

  def this(age: Int) {
    this()
    _age = age
  }

  def this(age: Int, name: String) {
    this(age)
    _name = name
  }
}

对象

1.伴生对象和孤立对象

伴生对象是伴生类的单例对象,没有定义伴生类的单利对象称为孤立对象。伴生对象的定义方式为:

//object People是class People的伴生对象,也是单例对象。同时在伴生对象中还可以实现static关键字,因为一个类只能生成一个伴生对象,而在伴生对象中定义的public方法和属性就是static的
class People{}

object People{
def eat = {println("people eat")}
}

//call
People.eat()

2.apply方法

apply定义在伴生对象中,可以通过类名.apply()形式调用,但是也可以省略apply,直接类名+参数的形式调用。apply方法可以重载

class Animal(name:String){
}

object Animal{
  def apply(param:String) = new Animal(param)
}

//call
val dog = Animal("dog")

3.unapply方法

unapply方法同apply方法一样定义在伴生对象中,不同的是,unapply用于提取类的属性

class Animal(val name:String){
}

object Animal{
  def apply(param:String) = new Animal(param)
  def unapply(a :Animal) :Option[(String)] = Some((a.name))
}

//call
val Animal(name) = Animal("dog")
//name属性的值被提出来
println("animal's name="+name)

类和特质

抽象类

抽象类需要加abstract关键字,在类中定义的属性不赋初值,即为抽象字段;方法不定义方法体为抽象方法
扩展类通过关键字extend继承抽象类,其中,抽象类和抽象字段可以不使用override关键字修饰,但是抽象类里面的非抽象方法必须通过关键字abstract实现

abstract class AbsCar {
  val name:String
  def print():Unit
  def geeting = println("welcome to my car")
}

class BMWCar extends AbsCar {
  val name: String = "BMW"

  def print: Unit = println("car name is " + name)

  override def geeting: Unit = super.geeting
}

option类

在返回值可能为null的情况下,尽可能将返回值包装为Option类型,这样,在获取返回值的时候,可以使用getOrElse方法获取一个默认对象,而不是判断是否为空或者出现nullPointExcption

trait特质

使用trait声明一个特质,特质和接口类似。
当只有一个基类需要继承,或者只有一个trait需要混入时,子类使用extend关键字。但是当有多个特质需要混入时,应该extend后加with关键字,声明需要混入的特质

函数

在面向过程(C语言)和面向对象(C++、Java)的编程语言中,值、结构体、对象是可以赋值传递的。在函数式语言中,函数也是可以通过赋值来传递的,类似于C的函数指针,但是更强大

函数变量

方法(函数)定义:

def counter(num:Int):Int  = num + 1

和变量的定义相似,函数也有类型和值。参数类型Int+返回值类型Int构成了函数的类型,函数的值就是入参num+函数体。由此,我们可以这样定义一个函数:

//变量名num:变量类型Int = 变量值10
val num:Int = 10
//变量名counter:变量类型(Int => Int) = 变量值(value) => {value+1}
val counter:(Int => Int) = (value) => {value+1}

lambda表达式

函数有匿名函数,就是无需定义函数名的函数,也就是lambda表达式。

匿名函数的定义:(参数名:参数类型,参数名:参数类型...) => {函数体}

(value:Int) => {value/2}

下划线

_标识那些在函数中只出现一次的变量,比如:

//等价于lambda表达式:(value:Int) => value+1
(_:Int) + 1

高阶函数

//2的x次方
def powerOfTow(x: Int): Int = if (x <= 0) 1 else x * powerOfTow(x - 1)

//l+(l+1)+...r
def sumInts(l: Int, r: Int): Int = if (l > r) 0 else l + sumInts(l + 1, r)

//l的平方+(l+1)的平方+..+r的平方
def sumSequars(l: Int, r: Int): Int = if (l > r) 0 else l * l + sumSequars(l + 1, r)

//2的l次方+2的(l+1)次方+...+2的r次方
def sumPowerofTwo(l: Int, r: Int): Int = if (l > r) 0 else powerOfTow(l) + sumPowerofTwo(l + 1, r)

//高阶函数,参数也是函数
def sum(f: Int => Int, l: Int, r: Int): Int = if (l > r) 0 else f(l) + sum(f, l + 1, r)

println(sum(x => x, 1, 5))
println(sum(x => x * x, 1, 5))
println(sum(powerOfTow, 1, 5))

容器的遍历和映射

val f = println(_:Int)
val list = List(1,2,3)
list.foreach(f)
println(list.map(a => a * 2))

val strs = List("Apache","Hadoop","spark")
println(strs.flatMap(a => a.toList))

filter和reduce

val list = List(1, 2, 3, 4, 5);
println(list.filter(i => i%2 == 0))
    
println(list.reduce((a,b) => a+b))
println(list map (_.toString) reduce ((x, y) => s"f($x,$y)"))

println(list reduceLeft (_ - _))
println(list reduceRight (_ - _))
println(list.fold(10)(_ * _))
posted @ 2019-06-09 22:53  gitmoji  阅读(221)  评论(0编辑  收藏  举报