Scala简述

1.安装

首先进入scala-ide 主页,了解最新情形。注意scala-ide并不是一个独立的ide,它只是eclipse的一个插件。
进入下载界面,获取最新下载链接–“http://download.scala-ide.org/sdk/lithium/e44/scala211/stable/site ”,特别注意该下载链接所适用的JDK和eclipse等版本,比如上述下载链接的系统需求为:JDK–6,7,8均可;Eclipse 4.4 (Luna) and Eclipse 4.5 (Mars)均可。


2.问题

问题1:安装插件后,打开eclpse,显示jdt未激活

此问题是由于下载的插件版本与eclipse不匹配造成的,卸载重装。

问题2

More than one scala library found in the build path (/home/asin/.eclipse/org.eclipse.platform_4.4.2_1786068630_linux_gtk_x86_64/plugins/org.scala-lang.scala-library_2.11.7.v20150622-112736-1fbce4612c.jar, /home/asin/SoftWare/spark-1.4.1-bin-hadoop2.6/lib/spark-assembly-1.4.1-hadoop2.6.0.jar).At least one has an incompatible version. Please update the project build path so it contains only one compatible scala library. test Unknown Scala Classpath Problem

    该问题是指由于导入的scala包和spark包不兼容,导致部分包重复。此时,往往是因为scala的版本过高的问题,右击工程,选择Scala->Set the Scala Installation,选择2.10.5即可。

3.语法

 //使用val定义的变量值是不可变的,相当于java里用final修饰的变量
val i = 1
//使用var定义的变量是可变得,在Scala中鼓励使用val
var s = "hello"

方法

def m1(x:Int,y:Int) :Int=x*y 方法的返回值类型可以不写,编译器可以自动推断出来,但是对于递归函数,必须指定返回类型

函数

val f1=(x:Int,y:Int)=>x+y
在函数式编程语言中,函数是“头等公民”,它可以像任何其他数据类型一样被传递和操作

案例:首先定义一个方法,再定义一个函数,然后将函数传递到方法里面

def m2(f:(Int,Int)=>Int)=f(2,6)
val f2=(x:Int,y:Int)=>x-y
m2(f2)   (=-4)

定义数组

val arr = Array(1,2,3,4,5,6,7,8)

映射

val sc=Map("tom"->85,"jim"->99)(箭头定义)
val sc=Map(("tom",85),("jim",99))(元组定义)
sc("tom") (获取值)
    注意:在Scala中,有两种Map,一个是immutable包下的Map,该Map中的内容不可变;另一个是mutable包下的Map,该Map中的内容可变
首先导入 import scala.collection.mutable.Map
sc("tom")=88(修改map中的值)
sc+=("kitty"->99) (追加)

元组

val t=("li",3.14,100)
val r1=t._1 (下标访问,从1开始)

集合

Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质
在Scala中集合有可变(mutable)和不可变(immutable)两种类型,immutable类型的集合初始化后就不能改变了(注意与val修饰的变量进行区别)

序列

不可变的序列 import scala.collection.immutable._
在Scala中列表要么为空(Nil表示空列表)要么是一个head元素加上一个tail列表。
9 :: List(5, 2) :: 操作符是将给定的头和尾创建一个新的列表
注意::: 操作符是右结合的,如9 :: 5 :: 2 :: Nil相当于 9 :: (5 :: (2 :: Nil))

object ImmutListDemo {

  def main(args: Array[String]) {
    //创建一个不可变的集合
    val lst1 = List(1,2,3)
    //将0插入到lst1的前面生成一个新的List
    val lst2 = 0 :: lst1
    val lst3 = lst1.::(0)
    val lst4 = 0 +: lst1
    val lst5 = lst1.+:(0)

    //将一个元素添加到lst1的后面产生一个新的集合
    val lst6 = lst1 :+ 3

    val lst0 = List(4,5,6)
    //将2个list合并成一个新的List
    val lst7 = lst1 ++ lst0
    //将lst1插入到lst0前面生成一个新的集合
    val lst8 = lst1 ++: lst0

    //将lst0插入到lst1前面生成一个新的集合
    val lst9 = lst1.:::(lst0)

    println(lst9)
  }
}
可变的序列 import scala.collection.mutable._
import scala.collection.mutable.ListBuffer

object MutListDemo extends App{
    //构建一个可变列表,初始有3个元素1,2,3
    val lst0 = ListBuffer[Int](1,2,3)
    //创建一个空的可变列表
    val lst1 = new ListBuffer[Int]
    //向lst1中追加元素,注意:没有生成新的集合
    lst1 += 4
    lst1.append(5)
    //将lst1中的元素最近到lst0中, 注意:没有生成新的集合
    lst0 ++= lst1
    //将lst0和lst1合并成一个新的ListBuffer 注意:生成了一个集合
    val lst2= lst0 ++ lst1
    //将元素追加到lst0的后面生成一个新的集合
    val lst3 = lst0 :+ 5
不可变的Set
import scala.collection.immutable.HashSet
object ImmutSetDemo extends App{
          val set1 = new HashSet[Int]()
      //将元素和set1合并生成一个新的set,原有set不变
      val set2 = set1 + 4
      //set中元素不能重复
      val set3 = set1 ++ Set(5, 6, 7)
      val set0 = Set(1,3,4) ++ set1
      println(set0.getClass)
}
可变的Set
import scala.collection.mutable
object MutSetDemo extends App{
      //创建一个可变的HashSet
      val set1 = new mutable.HashSet[Int]()
      //向HashSet中添加元素
      set1 += 2
      //add等价于+=
      set1.add(4)
      set1 ++= Set(1,3,5)
      println(set1)
      //删除一个元素
      set1 -= 5
      set1.remove(2)
      println(set1)
}
Map
import scala.collection.mutable
object MutMapDemo extends App{
      val map1 = new mutable.HashMap[String, Int]()
      //向map中添加数据
      map1("spark") = 1
      map1 += (("hadoop", 2))
      map1.put("storm", 3)
      println(map1)
      //从map中移除元素
      map1 -= "spark"
      map1.remove("hadoop")
      println(map1)
}

class定义。不用写public,默认public

构造器

    在scala中,如果不指定主构造函数,编译器将创建一个主构造函数的构造函数。 所有类的主体的声明都被视为构造函数的一部分。它也被称为默认构造函数。

class Student{
println("Hello from default constructor");
}

1.定义类的时候,就定义了构造器。即:是()内的内容。
2.主构造器会将类定义{}里的所有语句执行一次。
3.如果主构造器参数不带val或var,那么会根据是否被方法使用来决定。
4.如果不带val或var的参数被方法使用了,它会变为对象私有字段;
5.如果没有被方法使用,则被当成一个普通的参数,不升级成字段。

Scala提供了一个类的主构造函数的概念。如果代码只有一个构造函数,则可以不需要定义明确的构造函数。它有助于优化代码,可以创建具有零个或多个参数的主构造函数。
可以在类中创建任意数量的辅助构造函数,必须要从辅助构造函数内部调用主构造函数。this关键字用于从其他构造函数调用构造函数。当调用其他构造函数时,要将其放在构造函数中的第一行。

单例对象

java中main入口需要是静态static方法,scala没有static。所以
在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的。如Array.toString。对象的构造器在第一次使用的时候会被调用,如果一个对象从未被使用,那么他的构造器也不会被执行;对象本质上拥有类(scala中)的所有特性

object SingletonDemo {
def main(args: Array[String]) {
//单例对象,不需要new,用【类名.方法】调用对象中的方法
val session = SessionFactory.getSession()
println(session)
}
}
object SessionFactory{
//该部分相当于java中的静态块
var counts = 5
val sessions = new ArrayBuffer[Session]()
while(counts > 0){
sessions += new Session
counts -= 1
}
//在object中的方法相当于java中的静态方法
def getSession(): Session ={
sessions.remove(0)
}
class Session{
}

伴生对象

    与类名相同的对象叫做伴生对象,类和伴生对象之间可以相互访问私有的方法和属性

apply方法

通常我们会在类的伴生对象中定义apply方法,当遇到类名(参数1,...参数n)时apply方法会被调用

应用程序对象

Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法

trait

在java中可以通过interface实现多重继承,在Scala中可以通过特征(trait)实现多重继承,不过与java不同的是,它可以定义自己的属性和实现方法体,在没有自己的实现方法体时可以认为它时java interface是等价的,在Scala中也是一般只能继承一个父类,可以通过多个with进行多重继承。
trait TraitA{}
trait TraitB{}
trait TraitC{}
object Test1 extends TraitA with TraitB with TraitC{}

样本类

添加了case的类便是样本类。这种修饰符可以让Scala编译器自动为这个类添加一些语法上的便捷设定。如下:

1.添加与类名一致的工厂方法。也就是说,可以写成Var("x")来构造Var对象。
2.样本类参数列表中的所有参数隐式获得了val前缀,因此它被当作字段维护。
3.编译器为这个类添加了方法toString,hashCode和equals等方法。

模式匹配

就像switch case,不同在于

1. match表达式始终以值作为结果,这是Scala表达式的特点
2. Scala的备选项表达式永远不会意外掉入到下一个分支。在C或其他类C语言中,每个分支末尾要显式使用break语句来退出switch。
3. 如果没有模式匹配,MatchError异常会抛出。意味着必须确信所有的情况都考虑到,或者至少可以添加一个默认情况什么事都不做。如 case _ =>

模式的种类

  1. 通配模式:case _ => 。表示默认的全匹配备选项。通配模式还可以用来忽略对象中不关心的部分。如:case BinOp(,,_) => XXX,则表示不关心二元操作符的元素是什么,只是检查是否为二元操作符

  2. 常量模式 :仅匹配自身。任何字面量都可以用作常量。包括String类型。另外,任何的val或单例对象也可以被用作常量。如,单例对象Nil是只匹配空列表的模式。

  3. 变量模式 :变量模式类似于通配符,可以匹配任何对象。不同点在于,Scala把变量绑定在匹配的对象上。之后就可以使用这个变量操作对象。如: cop
    expr match{ case 0 => "zero" case somethingElse => "not zero" + somethingElse }       

    有一个注意点:Scala使用了一个简单的文字规则来区分是一个常量还是一个变量:用小写字母开始的简单名被当作是模式变量。

  4. 构造器模式:它的存在使得模式匹配真正变得强大。它由名称及若干括号之内的模式构成。如BinOp(“+” , e , Number(0))。

  5. 序列模式:可像匹配样本类那样匹配List或Array这样的序列类型。同样的语法现可以指定模式内任意数量的元素。如:expr match{ case List(0 , _ , _ ) => println(“found it”) case _ => }

    • 如果想匹配一个不指定长度的序列,可以指定_*作为模式的最后元素。它能匹配序列中0到任意数量的元素。
  6. 元组模式:例子

`def tupleDemo(expr : Any) =   
  expr match {  
    case (a , b, c) => println("matched " + a + b + c)  
    case _ =>   
  }  `

7.类型模式:可以把它当做类型测试和类型转换的简易替代。例如:
def generalSize(x : Any) = x match{
case s : String => s.length
case m : Map[_ , _] => m.size
case _ => 1
}

使用:

scala> generalSize(Map(1 -> 'a' , 2 -> 'b'))
    res15 : Int = 2

另:在Scala里类型测试和转换的代码很冗长,因为不建议这么做。 viecase BinOp("+" , x , x ) => BinOp("*" , x , Number(2))

模式守卫:

模式变量仅允许在模式中出现一次。如:
   这种写法就会出错。可以改成: case BinOp("+" , x , y ) if x == y => BinOp("*" , x , Number(2))
   模式守卫接在模式之后,开始于if。守卫可以是任意的引用模式中变量的布尔表达式。如果存在模式守卫, 那么只有在守卫返回true的时候匹配才成功。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值