C#程序员的Scala之路第二章(集合)

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。

C#程序员的Scala之路第二章(集合)_第1张图片

这就是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的继承关系:

C#程序员的Scala之路第二章(集合)_第2张图片

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编程中文版)。

 

你可能感兴趣的:(scala)