1.带参数的参数化数组
val big = new String("Hello")
Sacla 里可以使用new 实例化对象或类实例,当你在Scala 里实例化对象,可以使用值和类型把它参数化,如上面所示:
val str = new Array[String](3) str(0) = "Hello" str(1) = ", " str(2) = "world!\n"
Sacla里构造数组的方式,与大多数语言基本都差不多,但是上面的代码可以简化,但是如果你像更加具体的定义数组的话则如下所示:
val str: Array[String] = new Array[String](3) str(0) = "Hello" str(1) = ", " str(2) = "world!\n"
我们来看看简洁版吧:
val str = ("Hello","World","!")
其实上面这个代码调用了Array.apply("Hello", "World", "!") 工厂方法,该方法返回初始化创造一个新的数组并且返回。
来将 Hello World ! 输出吧。
val str = Array.apply("Hello", "World", "!", "") for (i <- 0 to 2) println(str(i))
Sacla 对待任何事物上追求概念的简洁性,从数组到表达式包括带有方法的对象。
2.使用List
Array是可变序列,什么意思呢?就是Array数组里的值是可变的,好比Array(0) = "15"
List是不可变序列,List不允许修改元素内的值。
创建List
val list = List(1,2,3) list.foreach { x => println(x) }
我们来试着修改list的值
list(0) = 2
给list 赋值的时候会报一个编译期的错误。
value update is not a member of List[Int]
如果将list的类型改为 var也是不行的。
如果真相改变List只有调用它的update方法,而update方法则是返回一个新的List集合
object Hello extends App { val list = List(1, 2, 3) println("返回更新后的新的List:") println(list.updated(0, 15)) println("返回原List:") println(list) }
Scala的List总是不可变的,它是为了Scala的函数式设计的,List的叠加功能
object Hello extends App { val listA = List(1, 2, 3) val listB = List(5,6,7) val listC = listA::listB println(listA) println(listB) println(listC) }
::符号是实现叠加功能,将一个元素的组合,添加到list的最前面如:
println(1:: listA)
但是如果你像把1加载后面就不行,会报一个语法错误,所以::符号总是对右边的操作数进行操作
Nil是Scala里面的空类所以以下代码是一种新的初始化List代码
val list = 1 :: 2 :: 3 :: Nil println(list)
下面是Scala 的一些常用方法和作用
List() 或 Nil 空List List("Cool", "tools", "rule) 创建带有三个值"Cool","tools"和"rule"的新List[String] val thrill = "Will"::"fill"::"until"::Nil 创建带有三个值"Will","fill"和"until"的新List[String] List("a", "b") ::: List("c", "d") 叠加两个列表(返回带"a","b","c"和"d"的新List[String]) thrill(2) 返回在thrill列表上索引为2(基于0)的元素(返回"until") thrill.count(s => s.length == 4) 计算长度为4的String元素个数(返回2) thrill.drop(2) 返回去掉前2个元素的thrill列表(返回List("until")) thrill.dropRight(2) 返回去掉后2个元素的thrill列表(返回List("Will")) thrill.exists(s => s == "until") 判断是否有值为"until"的字串元素在thrill里(返回true) thrill.filter(s => s.length == 4) 依次返回所有长度为4的元素组成的列表(返回List("Will", "fill")) thrill.forall(s => s.endsWith("1")) 辨别是否thrill列表里所有元素都以"l"结尾(返回true) thrill.foreach(s => print(s)) 对thrill列表每个字串执行print语句("Willfilluntil") thrill.foreach(print) 与前相同,不过更简洁(同上) thrill.head 返回thrill列表的第一个元素(返回"Will") thrill.init 返回thrill列表除最后一个以外其他元素组成的列表(返回List("Will", "fill")) thrill.isEmpty 说明thrill列表是否为空(返回false) thrill.last 返回thrill列表的最后一个元素(返回"until") thrill.length 返回thrill列表的元素数量(返回3) thrill.map(s => s + "y") 返回由thrill列表里每一个String元素都加了"y"构成的列表(返回List("Willy", "filly", "untily")) thrill.mkString(", ") 用列表的元素创建字串(返回"will, fill, until") thrill.remove(s => s.length == 4) 返回去除了thrill列表中长度为4的元素后依次排列的元素列表(返回List("until"))
thrill.reverse 返回含有thrill列表的逆序元素的列表(返回List("until", "fill", "Will"))
thrill.sort((s, t) => s.charAt(0).toLowerCase < t.charAt(0).toLowerCase) 返回包括thrill列表所有元素,并且第一个字符小写按照字母顺序排列的列表(返回List("fill", "until", "Will"))
thrill.tail 返回除掉第一个元素的thrill列表(返回List("fill", "until"))
3.使用Tuple
Tuple是元组,与List一样元组也是不可变的,但与List不同元组可以包含不同类型的元素。
val tuple = (99, "Luftballons")
println(tuple._1)
println(tuple._2)
这个是个好东西,封装多个对象并返回,变成一个元组,C#里面,C#的语法
Tuple<String, int, double> tuple = new Tuple<string, int, double>("", 12, 12.00) 是.net framwork 4.0新加入的
Scala里面元组的实际类型取决于他含有元素的数量和这些元组的类型如val tuple = (99, "Luftballons") 他的类型是Tuple[Int,String]
4使用Set和Map
定义一个Set,Set的定义方法很简单
object Hello extends App { var set = Set("Hello",100,11.2,'H') set += "World!" println(set) }
但是这段小小的代码隐藏了很多的东西,Set分可变和不可变2种,默认的都是创建不可变得Set,那他的set += "World!" 是什么意思呢?
其实set += "World!" 等价于 set = set + "World!"最后返回的Set是一个全新的Set,而不是原来的Set
默认创建的Set都是不可变的,如果需要可变你需要引用这个import scala.collection.mutable.Set包如下,创建的就是可变得Set。
import scala.collection.mutable.Set object Hello extends App { val set = Set("Hello",100,11.2,'H') set +="100" println(set) }
一开始我十分迷惑为什么不可变的集要赋成var 可变集要赋成val,经过我同事的解答,var这个是告诉你这个指针允许重新赋值,而val则告诉你这个指针不允许重新赋值。
而val改变的就是set本身的值,而var 则是改变set的指针,使它完全是一个新的set。
这就是Set 的继承关系,immutable 为不可变,mutable 为可变,默认使用都为不可变。
Map是Scala的另一种集合类(下面的是可变集):
import scala.collection.mutable.Map object Hello extends App { val map = Map[Int,String]() map +=(1 -> "Hello") map +=(2 -> "World") map +=(3 -> "!") println(map(2)) }
可变集都要引入scala.collection.mutable 包,而默认的都是不可变集如下:
object Hello extends App { var map = Map[Int,String]() map +=(1 -> "Hello") map +=(2 -> "World") map +=(3 -> "!") println(map(2)) }
一定要记住var 与val 一个是修改的指针,一个是修改的指向地址的值。
Map的继承关系:
5.var 与val
在我以前接触的C#编程里面,修改一个数组里的值,或者对象里的值是很平常的一件事,而函数式编程却鼓励我们使用val,为什么呢?
虽然val会造成资源上的浪费,但是机器在发展,硬件在发展,以前不是也争论过C#与C++,java与C++ 吗?
围绕的就是一个性能与语言的易读性,其实这不是我们所涉及的范围,我们所涉及的是那种语言好用,那种语言简洁而不是性能,
我说的不是程序的性能,而是语言的性能,程序的性能是需要程序员去考虑的,而语言的性能是需要编译器与语言的创造者去考虑的。
以上都是个人的理解,但是Scala鼓励我们要使用val
以下代码是有var的循环:
object Hello extends App { def printArray(array : Array[String]) : Unit={ var i = 0 while(i<array.length) { println(array(i)) i +=1 } } val a = Array[String]("1","2","3") printArray(a) }
去掉 var :
object Hello extends App { def printArray(array : Array[String]) : Unit={ array.foreach { x => printf(x) } } val a = Array[String]("1","2","3") printArray(a) }
在进一步优化代码
object Hello extends App { def printArray(array : Array[String]) : Unit=array.foreach { x => println(x) } printArray(Array[String]("1","2","3")) }
但是这个函数是有副作用的,什么是副作用,没有返回结果的函数都是有副作用的,没有结果的函数默认返回Unit
下面就更像一个函数编程了
object Hello extends App { def GetArray(array : Array[String])= array.mkString("\n") println(GetArray(Array("1","2","3"))) }
Scala让我们多使用val只有特定需要和判断的时候才使用var,可变对象和有副作用的方法(详见Scala编程中文版)。