scala 学习二

1、控制语句

1、if:基本与java相同,有一点与Java不同的是,Scala中的if表达式的值可以赋值给变量

val x = 1
val a = if (x>0) 5 else -5

2、while、do-while与java完全相同。
3、for循环:
1)Scala中的for循环语句格式如下:for (变量<-表达式) 语句块

for (i <- 1 to 5) println(i)

1 to 5为Range表达式。
(1 to 10).by(1).toList。Range表达式转换为listby后面是步长

2)有的时候,我们需要加一个过滤条件,这个就叫做守卫表达式,例如只输出10以内的偶数

for (i <- 1 to 10 if i%2==0) println(i)

3)Scala也支持“多个生成器”的情形,可以用分号把它们隔开。就相当于java的内循环

 for(i <- 1 to 3; j <- 4 to 8)
    println("i="+i+".j="+j)
    结果:
    i=1.j=4
    i=1.j=5
    i=1.j=6
    i=1.j=7
    i=1.j=8
    i=2.j=4
    i=2.j=5
    i=2.j=6
    i=2.j=7
    i=2.j=8
    i=3.j=4
    i=3.j=5
    i=3.j=6
    i=3.j=7
    i=3.j=8

4)多个生成器也可以和守卫联合使用

for(i <- 1 to 5 if i%2==0; j <- 4 to 8 if i!=j)
    println("i="+i+".j="+j)
    结果:
    i=2.j=4
    i=2.j=5
    i=2.j=6
    i=2.j=7
    i=2.j=8
    i=4.j=5
    i=4.j=6
    i=4.j=7
    i=4.j=8

5)for推导式 yield:yield进行处理,把处理结果塞到之前的集合中,返回

 var list = for( i <- 1 to 10) yield i%2
    list foreach(i => println(i))

2、数据结构

1、元组:
元组是不同类型的值的聚集。元组和列表不同,列表中各个元素必须是相同类型,而元组可以包含不同类型的元素。

 var tuple = ("str",1,3,2);
    print(tuple._1);

2、集
集(set)是不重复元素的集合。列表中的元素是按照插入的先后顺序来组织的,但是,”集”中的元素并不会记录元素的插入顺序,而是以“哈希”方法对元素的值进行组织,所以,它允许你快速地找到某个元素。
集包括可变集和不可变集,缺省情况下创建的是不可变集,通常我们使用不可变集。

  var set = Set("abc","def");
    set += "hig";
    set foreach (i => println(i))

如果是变量是val就会报错,因为val定义的是不可变的常量,var定义的是可以变的变量,set+”hig”之后,生成的新set(暂时用set2)已经不是之前的set了,在程序中,直接把set2的地址又指向了set。
3、映射
1、在Scala中,映射(Map)是一系列键值对的集合,也就是,建立了键和值之间的对应关系。在映射中,所有的值,都可以通过键来获取。
映射包括可变和不可变两种,默认情况下创建的是不可变映射,如果需要创建可变映射,需要引入scala.collection.mutable.Map包。

 var map = Map("key1" -> "value1", "key2" -> "value2");
    if (map.contains("key1"))
      println(map("key1"))
    else
      println(0)
      结果:value1

2、跟集类似,var变量也可以通过

 map += ("key3" -> "value3")

添加。
如果是val定义变量或报错,如果必须要定义val常量,则需要

import scala.collection.mutable.Map

3、遍历map

for ((k,v) <- 映射) 语句块

 for( (k,v) <- map) println(k+":"+v);

也可以只遍历其中的key或者value

 for(i <- map.keys)println(i +":" + map(i))
 for(i <- map.values)println(i )

4、迭代器
在Scala中,迭代器(Iterator)不是一个集合,但是,提供了访问集合的一种方法。当构建一个集合需要很大的开销时(比如把一个文件的所有行都读取内存),迭代器就可以发挥很好的作用。
迭代器包含两个基本操作:next和hasNext。next可以返回迭代器的下一个元素,hasNext用于检测是否还有下一个元素。

有了这两个基本操作,我们就可以顺利地遍历迭代器中的所有元素了。
通常可以通过while循环或者for循环实现对迭代器的遍历。

val iter = Iterator("Hadoop","Spark","Scala")
while (iter.hasNext) {
    println(iter.next())
}
val iter = Iterator("Hadoop","Spark","Scala")
for (elem <- iter) {
    println(elem)
}

3、类

1、基本语法

class Counter {
    private var value = 0
    def increment(): Unit = { value += 1}
    def current(): Int = {value}
}

1、如果类修饰符都没有,就默认是public。
在Scala中不返回任何值,那么就用Unit表示,相当于Java中的void类型。方法的返回值,不需要靠return语句,方法里面的最后一个表达式的值就是方法的返回值,比如,上面current()方法里面只有一条语句“value”,那么,value的值就是该方法的返回值。
2、Unit后面的等号和大括号后面,包含了该方法要执行的具体操作语句。如果大括号里面只有一行语句,那么也可以直接去掉大括号,写成下面的形式:

class Counter {
    private var value = 0
    def increment(): Unit = value += 1 //去掉了大括号
    def current(): Int = {value}  //作为对比,这里依然保留大括号
}

或者,还可以去掉返回值类型和等号,只保留大括号,如下:

class Counter {
    private var value = 0
    def increment() {value += 1} //去掉了返回值类型和等号,只保留大括号
    def current(): Int = {value} //作为对比,这里依然保留原来形式
}

2、构造器
1、辅助构造器:
Scala构造器包含1个主构造器和若干个(0个或多个)辅助构造器。
我们首先认识一下辅助构造器。辅助构造器的名称为this,每个辅助构造器都必须调用一个此前已经定义的辅助构造器或主构造器,辅助构造器就相当于java中的构造方法。
2、主构造器:
Scala的每个类都有主构造器。但是,Scala的主构造器和Java有着明显的不同,Scala的主构造器是整个类体,需要在类名称后面罗列出构造器所需的所有参数,

class Test1 {//主构造器
  var a = 1;
  private var in="";
  def this(in : String){//辅助构造器
    this();//调用主构造器
    this.in = in;
  }
  def tprin = {
    println(in);
  }
}

3、对象
1、单例对象:Scala并没有提供Java那样的静态方法或静态字段,但是,可以采用object关键字实现单例对象,具备和Java静态方法同样的功能

object Test3 {
   var a = 0;
  private var in="";

  def newTest={
    a+=1;
    println("第"+a+"个人")
  }
}

而且这个对象被引用的时候不需要new,直接可以使用

     (Test3).newTest
    (Test3).newTest
    (Test3).newTest
    //如果是正常class的类,实例化是需要new的
    (new Test1).newTest

2、伴生对象:
在Java中,我们经常需要用到同时包含实例方法和静态方法的类,在Scala中可以通过伴生对象来实现。当单例对象与某个类具有相同的名称时,它被称为这个类的“伴生对象”。类和它的伴生对象必须存在于同一个文件中,而且可以相互访问私有成员(字段和方法)。


object Test3 {
  var a = 0;
  private var in = "";

  def newTest = {
    a += 1;
    a
  }

 def main(args: Array[String]): Unit = {
 }

}
class Test3 {
  def test(name: String) = {
    var t = Test3.newTest
    println("第"+t+"个人的名字为"+name)
  }

}

4、继承
Scala中的继承与Java有着显著的不同:
(1)重写一个非抽象方法必须使用override修饰符。
(2)只有主构造器可以调用超类的主构造器。
(3)在子类中重写超类的抽象方法时,不需要使用override关键字。
(4)可以重写超类中的字段。
Scala和Java一样,不允许类从多个超类继承
抽象类

abstract class Car{   //是抽象类,不能直接被实例化
   val carBrand: String //字段没有初始化值,就是一个抽象字段
     def info() //抽象方法,不需要使用abstract关键字
     def greeting() {println("Welcome to my car!")}
}

说明几点:
(1)定义一个抽象类,需要使用关键字abstract。
(2)定义一个抽象类的抽象方法,也不需要关键字abstract,只要把方法体空着,不写方法体就可以。
(3)抽象类中定义的字段,只要没有给出初始化值,就表示是一个抽象字段,但是,抽象字段必须要声明类型,比如:
继承类:

class BMWCar extends Car {
    override val carBrand = "BMW"  //重写超类字段,需要使用override关键字,否则编译会报错
    def info() {printf("This is a %s car. It is on sale", carBrand)} //重写超类的抽象方法时,不需要使用override关键字,不过,如果加上override编译也不错报错
    override def greeting() {println("Welcome to my BMW car!")} //重写超类的非抽象方法,必须使用override关键字
}
object MyCar {  
    def main(args: Array[String]){
        val myCar1 = new BMWCar()
        val myCar2 = new BYDCar()
        myCar1.greeting()
        myCar1.info()       
        myCar2.greeting()
        myCar2.info()
    }
}

5、特质(trait)
Java中提供了接口,允许一个类实现任意数量的接口。在Scala中没有接口的概念,而是提供了“特质(trait)”,它不仅实现了接口的功能,还具备了很多其他的特性。Scala的特质,是代码重用的基本单元,可以同时拥有抽象方法和具体方法。Scala中,一个类只能继承自一个超类,却可以实现多个特质,从而重用特质中的方法和字段,实现了多重继承。
特质定义好以后,就可以使用extends或with关键字把特质混入类中。
6、模糊匹配
1、Scala的模式匹配最常用于match语句中。下面是一个简单的整型值的匹配实例。

val colorNum = 1
val colorStr = colorNum match {
    case 1 => "red"
    case 2 => "green"
    case 3 => "yellow"
    case _ => "Not Allowed" 
} 
println(colorStr)

另外,在模式匹配的case语句中,还可以使用变量。

val colorNum = 4
val colorStr = colorNum match {
    case 1 => "red"
    case 2 => "green"
    case 3 => "yellow"
    case unexpected => unexpected + " is Not Allowed"   
} 
println(colorStr)

输出结果是4 is Not Allowed

2、类型匹配:
Scala可以对表达式的类型进行匹配。

for (elem <- List(9,12.3,"Spark","Hadoop",'Hello)){
    val str  = elem match{
        case i: Int => i + " is an int value."
        case d: Double => d + " is a double value."
        case "Spark"=> "Spark is found."
        case s: String => s + " is a string value."
        case _ => "This is an unexpected value."
    }
println(str)    
}
9 is an int value.
12.3 is a double value.
Spark is found.
Hadoop is a string value.
This is an unexpected value.

3、”守卫(guard)”语句

for (elem <- List(1,2,3,4)){
      elem match {
          case _ if (elem %2 == 0) => println(elem + " is even.")
            case _ => println(elem + " is odd.")
    }
}
1 is odd.
2 is even.
3 is odd.
4 is even.

4、for表达式中的模式
for ((k,v) <- 映射) 语句块
对于遍历过程得到的每个值,都会被绑定到k和v两个变量上,也就是说,映射中的“键”被绑定到变量k上,映射中的“值”被绑定到变量v上。

for ((k,v) <- university) printf("Code is : %s and name is: %s\n",k,v)

结果

Code is : XMU and name is: Xiamen University
Code is : THU and name is: Tsinghua University
Code is : PKU and name is: Peking University

5、Option类型
标准类库中的Option类型用case类来表示那种可能存在、也可能不存在的值。
一般而言,对于每种语言来说,都会有一个关键字来表示一个对象引用的是“无”,在Java中使用的是null。Scala融合了函数式编程风格,因此,当预计到变量或者函数返回值可能不会引用任何值的时候,建议你使用Option类型。Option类包含一个子类Some,当存在可以被引用的值的时候,就可以使用Some来包含这个值,例如
Some(“天皇”)。而None则被声明为一个对象,而不是一个类,表示没有值
Option[Int] = None
Option类型还提供了getOrElse方法,这个方法在这个Option是Some的实例时返回对应的值,而在是None的实例时返回传入的参数。
在Scala里,经常会用到Option[T]类型,其中的T可以是Sting或Int或其他各种数据类型。Option[T]实际上就是一个容器,我们可以把它看做是一个集合,只不过这个集合中要么只包含一个元素(被包装在Some中返回),要么就不存在元素(返回None)。既然是一个集合,我们当然可以对它使用map、foreach或者filter等方法

  val books = Map("key1" -> "天皇","key2" -> "地煞", "key3" -> "菩提", "key4" -> "鸿气")
    books.get("key1").foreach(println)
    println(books.get("key1") + "test1")
    println(books.get("key1").getOrElse("没有这个书") + "test")
    println(books.get("key5").getOrElse("没有这个书") + "test")
结果:
天皇
Some(天皇)test1
Nonetest2
天皇test3
没有这个书test4
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值