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 _ =>
模式的种类
通配模式:case _ => 。表示默认的全匹配备选项。通配模式还可以用来忽略对象中不关心的部分。如:case BinOp(,,_) => XXX,则表示不关心二元操作符的元素是什么,只是检查是否为二元操作符
常量模式 :仅匹配自身。任何字面量都可以用作常量。包括String类型。另外,任何的val或单例对象也可以被用作常量。如,单例对象Nil是只匹配空列表的模式。
变量模式 :变量模式类似于通配符,可以匹配任何对象。不同点在于,Scala把变量绑定在匹配的对象上。之后就可以使用这个变量操作对象。如: cop
expr match{ case 0 => "zero" case somethingElse => "not zero" + somethingElse }
有一个注意点:Scala使用了一个简单的文字规则来区分是一个常量还是一个变量:用小写字母开始的简单名被当作是模式变量。
构造器模式:它的存在使得模式匹配真正变得强大。它由名称及若干括号之内的模式构成。如BinOp(“+” , e , Number(0))。
序列模式:可像匹配样本类那样匹配List或Array这样的序列类型。同样的语法现可以指定模式内任意数量的元素。如:expr match{ case List(0 , _ , _ ) => println(“found it”) case _ => }
- 如果想匹配一个不指定长度的序列,可以指定_*作为模式的最后元素。它能匹配序列中0到任意数量的元素。
元组模式:例子
`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的时候匹配才成功。