scala的一些特殊用法

1.建立多行字符串,只要把多行字符串放在3個雙引號間("""...""")便可。這是Scala對於here document,或者叫heredoc的支持。這裏咱們建立一個三行長的字符串:java

MultiLine.scala安全

val str = """Hello world!
How are you!
Good morning!"""
println(str)

輸出以下:app

Hello world!
How are you!
Good morning!
請按任意鍵繼續. . .

2.運算符優先級ide

Scala沒有定義運算符的優先級,但它定義了方法的優先級。函數

方法名的第一個字符決定了它的優先級。若是表達式裏面有兩個具備相同優先級的字符,那麼左邊的運算符優先級更高。下面從低到高列出了首字符的優先級:post

全部字母
|
^
&
< >
= !
:
+ -
* / %
全部其餘特殊字符

舉例以下:url

Complex.scalaspa

class Complex(val real:Int, val imag:Int) {
    def +(operand:Complex):Complex={
      println("Calling +")
      new Complex(real+operand.real , imag+operand.imag)
    }
    
    def *(operand:Complex):Complex={
      println("Calling *")
      new Complex(real*operand.real - imag*operand.imag , real*operand.imag + imag*operand.real )
    }
    override def toString():String = {
      real + (if(imag<0) ""else "+")+ imag + "i"
    }
}

object Complex extends App {
  val c1 = new Complex(1,4)
  val c2 = new Complex(2,-3)
  val c3 = new Complex(2,2)
//  val sum = c1 + c2
//  println("(" + c1 + ") + (" + c2 + ")=" + sum )
  println(c1+c2*c3)
}

運行結果以下:scala

Calling *
Calling +
11+2i

 3. 類繼承code

在scala裏,繼承一個基類跟Java的作法很類似,只是多了兩點限制:

(1)重寫方法須要override關鍵字

(2)只有主構造函數才能往基類構造函數中傳參數

下面是繼承一個基類的例子:

Vehicle.scala

class Vehicle(val id:Int, val year:Int) {
    override def toString(): String = "ID:" + id + " Year:" + year
}

class Cars(override val id:Int, override val year:Int, 
    var fuelLevel:Int)extends Vehicle(id,year){
  override def toString(): String = super.toString()+ " Fuel Level:" + fuelLevel
}

object Cars extends App {
  val car = new Cars(1, 2010, 100)
  println(car)
}

程序運行結果以下:

ID:1 Year:2010 Fuel Level:100

4. Scala中的static

Scala中沒有靜態字段和靜態方法。靜態字段和靜態方法會打破Scala所支持的完整的面向對象模型。不過,scala也是徹底支持類一級的屬性和操做的。這就是伴生對象的做用。

舉例以下:

Marker.scala

class Marker private(val color:String) {
    override def toString():String = "marker color "+color
}

object Marker extends App{
  private val markers = Map(
      "red" -> new Marker("red"),
      "blue" -> new Marker("blue"),
      "green" -> new Marker("green")
      )
      
  def primaryColors = "red, green, blue"
    
  def apply(color:String) = if(markers.contains(color))
    markers(color) else null
    
  println("Primary colors are:" + Marker.primaryColors)
  println(Marker("blue"))
  println(Marker("red"))
}

程序運行結果以下:

Primary colors are:red, green, blue
marker color blue
marker color red

 5. Option類型

Scala想讓意圖更清晰的表達出來,確實有時候咱們就須要沒有結果。Scala以一種類型安全的方式作到這一點:它使用Option[T]類型。舉例以下:

OptionExample.scala

object OptionExample extends App{
    def commentOnPractice(input:String) = {
      //rather than returning null
      if(input == "test") Some("good") else None
    }
    for(input <- Set("test","hack")){
      val comment = commentOnPractice(input)
      println("input "+input+"comment "+comment.getOrElse("Found no comments"))
    }
}

程序運行結果以下:

input testcomment good
input hackcomment Found no comments

將類型顯式聲明爲Option[String],Scala會強制咱們檢查實例的不存在。如此一來,就不太可能由於沒有檢查null引用而拋出NullPointerException。調用返回Option[T]的getOrElse()方法,能夠主動的應對結果不存在(None)的情形。

 6.方法返回類型推演

除了推演變量的類型,Scala也會嘗試推演方法返回值的類型。不過,這有個陷阱,推演會依賴於方法如何定義。若是用等號(=)定義方法,Scala就能夠推演返回類型。不然,它就假設方法是一個void方法。

7. 隱式類型轉換

舉例以下:

import java.util._
class DateHelper(number:Int) {
    def days(when:String):Date = {
      var date = Calendar.getInstance()
      when match {
        case DateHelper.ago => date.add(Calendar.DAY_OF_MONTH, -number)
        case DateHelper.from_now => date.add(Calendar.DAY_OF_MONTH, number)
        case _ => date
      }
      date.getTime();
    }
}

object DateHelper extends App{
    val ago = "ago"
    val from_now = "from_now"
    implicit def convertInt2DateHelper(number:Int) = new DateHelper(number)
    val past = 2 days ago
    val appointment = 5 days from_now
    println(past)
    println(appointment)
}

程序運行結果以下:

Fri Mar 13 16:49:06 CST 2015
Fri Mar 20 16:49:06 CST 2015

 7. 使用Set,合併Set集

若是須要將兩個Set合併成一個新的Set,能夠用++():

scala> val feeds1 = Set("blog.toolshed.com","pragdave.pragprog.com","pragmactic-
osxer.blogspot.com","vita-contemplativa.blogspot.com")
feeds1: scala.collection.immutable.Set[String] = Set(blog.toolshed.com, pragdave
.pragprog.com, pragmactic-osxer.blogspot.com, vita-contemplativa.blogspot.com)

scala> val feeds2 = Set("blog.toolshed.com","martinfowler.com/bliki")
feeds2: scala.collection.immutable.Set[String] = Set(blog.toolshed.com, martinfo
wler.com/bliki)

scala> val mergedFeeds = feeds1 ++ feeds2
mergedFeeds: scala.collection.immutable.Set[String] = Set(pragdave.pragprog.com,
 pragmactic-osxer.blogspot.com, vita-contemplativa.blogspot.com, blog.toolshed.c
om, martinfowler.com/bliki)

scala> println("# of merged feeds:" + mergedFeeds.size)
# of merged feeds:5

Set至多持有每一個元素一次,從輸出裏能夠看到這一點,在合併後的Set裏,兩個Set裏公共的元素只存儲一次:

若是想在每一個元素前面加上「http://",能夠用map()方法:

scala> val urls = feeds1 map("http://"+_)
urls: scala.collection.immutable.Set[String] = Set(http://blog.toolshed.com, http://pragdave.pragprog.com, http://pragmactic-osxer.blogspot.com, http://vita-con
templativa.blogspot.com)

若是準備對Set集進行迭代,一次一個的進行刷新,能夠用內建的迭代器foreach(),像這樣:

scala> feeds1 foreach{ feed => println(" Refreshing " + feed)}
 Refreshing blog.toolshed.com
 Refreshing pragdave.pragprog.com
 Refreshing pragmactic-osxer.blogspot.com
 Refreshing vita-contemplativa.blogspot.com

 8. 用Scala實現集合中相鄰元素間的差值

如何計算同一集合中元素兩兩之間的差值,即求集合(a,b,c,d)中的(b-a,c-b,d-c)

實現方法以下:

 

scala> val l1 = 1 to 10 toList
warning: there were 1 feature warning(s); re-run with -feature for details
l1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> val l2 = l1.tail
l2: List[Int] = List(2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> l1.zip(l2).map(p=>(p._2-p._1))
res1: List[Int] = List(1, 1, 1, 1, 1, 1, 1, 1, 1)

 

代碼含義解釋以下:

  1. tail表示一個集合中除首元素外的剩餘元素,也是一個集合。
  2. zip將兩個集合組成一個數值對集合,好比原來有兩個集合分別是(a,b,c,d), (1,2,3,4),使用zip以後,造成((a,1),(b,2),(c,3),(d,4)),若是兩個集合長度不一致,多餘元素將被捨去。
  3. map操做中的p._1和p._2表示tuple(元組)中的第一個元素和第二個元素
  • head和tail  head表示頭元素,tail表示除head以外的剩餘元素集合
  • init和last    last表示尾元素, init表示除尾元素以外的剩餘元素集合
相關文章
相關標籤/搜索