scala基础

Posted boboshenqi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 = [email protected]
//访问
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)(_ * _))

以上是关于scala基础的主要内容,如果未能解决你的问题,请参考以下文章

大数据学习06 Scala的基础语法

Scala 基础语法

「大数据」(八十六)Scala基础

Scala学习之路----基础入门

初学scala4——trait混入

Scala附加列表