1. 程式人生 > >Scala的常用小技巧

Scala的常用小技巧

-a 限定 tro imp efi targe 容易 final 不可見

1."RichString.java".stripSuffix(".java") == "RichString"

"http://my.url.com".stripPrefix("http://") == "my.url.com"

2.Scala中,訪問修飾符可以通過使用限定詞強調。格式為:private[x] protected[x],這裏的x指代某個所屬的包、類或單例對象。如果寫成private[x],讀作"這個成員除了對[…]中的類或[…]中的包中的類及它們的伴生對像可見外,對其它所有類都是private。這種技巧在橫跨了若幹包的大型項目中非常有用,它允許你定義一些在你項目的若幹子包中可見但對於項目外部的客戶卻始終不可見的東西。

3.保護(Protected)成員

在 scala 中,對保護(Protected)成員的訪問比 java 更嚴格一些。因為它只允許保護成員在定義了該成員的的類的子類中被訪問。而在java中,用protected關鍵字修飾的成員,除了定義了該成員的類的子類可以訪問,同一個包裏的其他類也可以進行訪問。

公共(Public)成員

Scala中,如果沒有指定任何的修飾符,則默認為 public。這樣的成員在任何地方都可以被訪問。

私有(Private)成員

用private關鍵字修飾,帶有此標記的成員僅在包含了成員定義的類或對象內部可見,同樣的規則還適用內部類。

4.@transient註解將字段標記為瞬態的,瞬態的字段不會被序列化,這對於需要臨時保存的緩存數據,或者是能夠很容易地重新計算的數據而言是合理的。

5.isAssignableFrom 是用來判斷一個類Class1和另一個類Class2是否相同或是另一個類的超類或接口。 通常調用格式是:Class1.isAssignableFrom (Class2)

而instanceof 是用來判斷一個對象實例是否是一個類或接口的或其子類子接口的實例。

6.編譯器可以自動插入 implicit 的最後一個用法是隱含參數。 比如編譯器在需要是可以把 someCall(a)修改為 someCall(a)(b)或者 new someClass(a) 修改為 new SomeClass(a)(b),也就是說編譯器在需要的時候會自動補充缺少的參數來完成方法的調用。其中(b)為一組參數,而不僅僅只最後一個參數。這裏更詳細

7.import java.util.concurrent.atomic.AtomicInteger

new AtomicInteger(0).getAndIncrement()獲取自增的id

8.class A {def method1: A = this } class B extends A (def method2: B = this} val b = new B

如果調用b.method2.method1是可以的,但是如果想調用b.method1.method2就不行了。因為method1返回的是A類型的。

當然你可以在B中覆蓋method1,以返回正確類型。但是scala中解決這個問題的辦法就是this.type

class A { def method1: this.type = this } class B extends A { def method2: this.type = this } val b = new B

如果調用b.method1則編譯器會知道method1返回的是B類型的。

9.ConcurrentHashMap是線程安全的,適合並發操作。

10.在Scala中並沒有枚舉類型,但在標準類庫中提供了Enumeration類來產出枚舉。擴展Enumeration類後,調用Value方法來初始化枚舉中的可能值。

內部類Value實際上是一個抽象類,真正創建的是Val。因為實際上是Val,所以可以為Value傳入id和name

如果不指定,id就是在前一個枚舉值id上加一,name則是字段名,鏈接

11.scala product2,product1

12.reflect.classTag[V].runtimeClass.getName反射獲取類名

13.Scala中的Either的兩個子類(Left,Right)的簡單用法

14.implicitly[ClassTag[T]]

15.要求require和斷言(assert)

要求(require)和斷言(assert)都起到可執行文檔的作用。兩者都在類型系統不能表達所要求的不變量(invariants)的場景裏有用。 assert用於代碼假設的不變量(invariants) (內部或外部的) 例如:(譯註,不變量 invariant 是指類型不可變,即不支持協變或逆變的類型變量)

val stream = getClass.getResourceAsStream("someclassdata")

assert(stream != null)

相反,require用於表達API契約:

def fib(n: Int) = { require(n > 0) ... }

16.Scala NonFatal

17.Just use Java‘s java.lang.ThreadLocal class to store the variables.

val tl = new ThreadLocal[String]
tl.set("fish")
tl.get // "fish"

18.Spark 閉包中ClosureCleaner操作

19.AtomicBoolean 在這個Boolean值的變化的時候不允許在之間插入,保持操作的原子性。這個方法主要兩個作用

1. 比較AtomicBoolean和expect的值,如果一致,執行方法內的語句。其實就是一個if語句

2. 把AtomicBoolean的值設成update 比較最要的是這兩件事是一氣呵成的,這連個動作之間不會被打斷,任何內部或者外部的語句都不可能在兩個動作之間運行。為多線程的控制提供了解決的方案

20.implicit ord: Ordering[T] = null

case class Person(name:String,tel:String) extends Ordered[Person] {
def compare(that: Person): Int = this.name compare that.name
}
val ps5 = Array(Person("peter","138"),Person("peter","55"),Person("john","138"))
sc.parallelize(ps5).distinct.collect。詳細解釋

21.

Scala中的=>符號可以看做是創建函數實例的語法糖。例如:A => T,A,B => T表示一個函數的輸入參數類型是“A”,“A,B”,返回值類型是T。請看下面這個實例:

val f: Int => String = myInt => "The value of myInt is: " + myInt.toString()

f: Int => String = <function1>

println(f(3))

The value of myInt is: 3

上面例子定義函數f:輸入參數是整數類型,返回值是字符串。

另外,() => T表示函數輸入參數為空,而A => Unit則表示函數沒有返回值

22.

scala>val input = List(3, 5, 7, 11)

scala> input.scanLeft(0)(_+_)

res0: List[Int] = List(0, 3, 8, 15, 26)

23.scala flatten

flatten可以把嵌套的結構展開.

scala> List(List(1,2),List(3,4)).flatten
res0: List[Int] = List(1, 2, 3, 4)

24。asScala

25.AtomicReference

java並發庫提供了很多原子類來支持並發訪問的數據安全性,除了常用的

AtomicInteger、AtomicBoolean、AtomicLong 外還有
AtomicReference 用以支持對象的原子操作:AtomicReference<V> 可以封裝引用一個V實例,
通過
public final boolean compareAndSet(V expect, V update)
可以支持並發訪問,set的時候進行對比判斷,如果當前值和操作之前一樣則返回false,否則表示數據沒有 變化,例如下面的代碼
使用 AtomicReference 實現了並發計數。這裏

26.

看scala的源碼的話很發現很多源碼開頭都有一句:self => 這句相當於給this起了一個別名為self。

self不是關鍵字,可以用除了this外的任何名字命名(除關鍵字)。就上面的代碼,在Self 內部,可以用this指代當前對象,也可以用self指代,兩者是等價的。這裏

class Self {
    self =>   //代表this指針  ,也就是說 self 就 this的別名
    val tmp = "scala"
    def foo = self.tmp + this.tmp
}

27

定長數組:指長度不可變的數組Array。

第一種方式:
先聲明一個數組,後初始化該數組:
scala> val array = new Array[Double](5)
array: Array[Double] = Array(0.0, 0.0, 0.0, 0.0, 0.0)
賦值方式:array(index) = value
第二種方式:
scala> val array = Array(1, 2, 3, 4, 5)
array: Array[Int] = Array(1, 2, 3, 4, 5)
第三種方式,Array.fill(length)(value):
scala> val array = Array.fill(5)(3.5)
array: Array[Double] = Array(3.5, 3.5, 3.5, 3.5, 3.5)
如果fill第二個參數只寫一個值的話,那麽該數組的所有元素都是該值,但是如果第二個參數是一個iterator或者random,那麽數組就會被賦值為它們的值。
scala> val array = Array.fill(2)(math.random)
array: Array[Double] = Array(0.2810736748034083, 0.7261142068882558)
第四種方式,ofDim[T](length):
scala> val array = Array.ofDim[Double](5)
array: Array[Double] = Array(0.0, 0.0, 0.0, 0.0, 0.0)
賦值方式:array(index) = value

Scala的常用小技巧