【Scala】Scala高级使用技巧之一

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/gongxifacai_believe/article/details/82110617

1、Scaladoc的使用

Scaladoc是Scala的API文档,包含了Scala所有的API以及使用说明,包括class、object、trait、function、method、implicit等。通过URL:http://www.scala-lang.org/api/current/#package,可以在线浏览Scaladoc。
以下是一些Scaladoc使用的tips:
(1)直接在左上角的搜索框中,搜索你需要的寻找的包、类即可;
(2)O和C,分别代表了某个类的伴生对象以及伴生类的概念;
(3)标记为implicit的方法,代表的是隐式转换;
(4)举例:搜索StringOps,可以看到String的增强类StringOps的所有方法说明。

2、跳出循环语句的3种方法

(1)方法一:使用boolean控制变量
while循环:

var flag = true
var res = 0
var n = 0

while(flag) {
  res += n
  n += 1
  if (n == 5) {
    flag = false
  }
}

for循环(高级for循环,加上了if守卫):

var flag = true
var res = 0

for (i <- 0 until 10 if flag) {
  res += i
  if (i == 4) flag = false
}

(2)方法二:在嵌套函数中使用return

def add_outer() = {
  var res = 0

  def add_inner() {
    for (i <- 0 until 10) {
      if (i == 5) {
        return
      }
      res += i
    }
  }

  add_inner()
  res
}

(3) 方法三:使用Breaks对象的break方法
跟java里面的break比较类似,相对来说,比较灵活好用;与breakable代码块配合使用。

import scala.util.control.Breaks._

var res = 0

breakable {
  for (i <- 0 until 10) {
    if (i == 5) {
      break;
    }
    res += i
  }
}

3、多维数组

多维数组:数组的元素还是数组,数组套数组,就是多维数组。
构造指定行与列的二维数组:Array.ofDim方法

val multiDimArr1 = Array.ofDim[Double](3, 4)
multiDimArr1(0)(0) = 1.0

构造不规则多维数组:

val multiDimArr2 = new Array[Array[Int]](3)
multiDimArr2(0) = new Array[Int] (1)
multiDimArr2(1) = new Array[Int] (2)
multiDimArr2(2) = new Array[Int] (3)
multiDimArr2(1)(1) = 1

4、Java数组ArrayList与Scala数组缓冲ArrayBuffer的隐式转换

Scala代码中,直接调用JDK(Java)的API,比如调用一个Java类的方法,势必可能会传入Java类型的list;Scala中构造出来的list,其实是ArrayBuffer;你直接把Scala的ArrayBuffer传入Java接收ArrayList的方法,肯定不行。
Scala的ArrayBuffer转换为Java的ArrayList:

import scala.collection.JavaConversions.bufferAsJavaList
import scala.collection.mutable.ArrayBuffer

val command = ArrayBuffer("javac", "C:\\Users\\Administrator\\Desktop\\HelloWorld.java")
val processBuilder = new ProcessBuilder(command)
val process = processBuilder.start()
val res = process.waitFor()

Java的ArrayList转换为Scala的ArrayBuffer:

import scala.collection.JavaConversions.asScalaBuffer
import scala.collection.mutable.Buffer

val cmd: Buffer[String] = processBuilder.command()

5、Java Map与Scala Map的隐式转换

Java Map转换为Scala Map:

import scala.collection.JavaConversions.mapAsScalaMap

val javaScores = new java.util.HashMap[String, Int]()
javaScores.put("Alice", 10)
javaScores.put("Bob", 3)
javaScores.put("Cindy", 8)

val scalaScores: scala.collection.mutable.Map[String, Int] = javaScores

Scala Map转换为Java Map:

import scala.collection.JavaConversions.mapAsJavaMap
import java.awt.font.TextAttribute._

val scalaAttrMap = Map(FAMILY -> "Serif", SIZE -> 12)
val font = new java.awt.Font(scalaAttrMap)

6、Tuple拉链操作

Tuple拉链操作指的就是zip操作。zip操作是Array类的方法,用于将两个Array合并为一个Array。比如Array(v1)和Array(v2),使用zip操作合并后的格式为Array((v1,v2)),合并后的Array的元素类型为Tuple。

val students = Array("Leo", "Jack", "Jen")
val scores = Array(80, 100, 90)
val studentScores = students.zip(scores)

for ((student, score) <- studentScores)
  println(student + " " + score)

如果Array的元素类型是个Tuple,调用Array的toMap方法,可以将Array转换为Map。

studentScores.toMap

7、内部类与外部类

(1)内部类的作用域:外部类对象

import scala.collection.mutable.ArrayBuffer

class Class {
  class Student(val name: String) 
  val students = new ArrayBuffer[Student]
  def register(name: String) =  {
    new Student(name)
  }
}

val c1 = new Class
val leo = c1.register("leo")
c1.students += leo

val c2 = new Class
val jack = c2.register("jack")
c1.students += jack

(2)扩大内部类作用域:伴生对象

object Class {
  class Student(val name: String)
}

class Class {
  val students = new ArrayBuffer[Class.Student]
  def register(name: String) = {
    new Class.Student(name)
  }
}

val c1 = new Class
val leo = c1.register("leo")
c1.students += leo

val c2 = new Class
val jack = c2.register("jack")
c1.students += jack

(3)扩大内部类作用域:类型投影

class Class {
  class Student(val name: String) 
  val students = new ArrayBuffer[Class#Student]
  def register(name: String) =  {
    new Student(name)
  }
}

val c1 = new Class
val leo = c1.register("leo")
c1.students += leo

val c2 = new Class
val jack = c2.register("jack")
c1.students += jack

(4)内部类获取外部类的引用

class Class(val name: String) { outer =>
  class Student(val name: String) {
    def introduceMyself = "Hello, I'm " + name + ", I'm very happy to join class " + outer.name
  }
  def register(name: String) =  {
    new Student(name)
  }
}

val c1 = new Class("c1")
val leo = c1.register("leo")
leo.introduceMyself

8、package

package是用来对多个同名的类进行命名空间的管理,避免同名类发生冲突。
比如,scala.collection.mutable.Map和scala.collection.immutable.Map。
(1)package的定义
1.  package定义的第一种方式:多层级package定义。

package com {
	package ibeifeng {
		package scala {
			class Test {}
		}
	}
}

2.  package定义的第二种方式:串联式package定义。

package com.ibeifeng.scala {
	package service {
		class Test {}
	}
}

3.  package定义的第三种方式:文件顶部package定义。

package com.ibeifeng.scala.service

class Test {

}

4.  package定义的第四种方式:IDE自动生成包。
(2)package的特性
1.  package特性一:同一个包定义,可以在不同的scala源文件中的; 一个scala源文件内,可以包含两个包。

## Test1.scala

package com {
	package ibeifeng {
		package scala {
			class Test1
		}
	}
}
## Test2.scala

package com {
	package ibeifeng {
		package scala {
			class Test2
		}
	}
}
## Test3.scala

package com {
	package ibeifeng {
		package scala1 {
			class Test
		}
	}
}

package com {
	package ibeifeng {
		package scala2 {
			class Test
		}
	}
}

2.  package特性二:子包中的类,可以访问父包中的类。

## Test.scala

package com {
	package ibeifeng {
		package scala {
			object Utils {
				def isNotEmpty(str: String): Boolean = str != null && str != ""
			}
			
			class Test
		
			package service {
				class MyService {
					def sayHello(name: String) {
						if(Utils.isNotEmpty(name)) {
							println("Hello, " + name)
						} else {
							println("Who are you?")  
						}
					}
				}
			}
		}
	}
}

object MainClass {
  def main(args: Array[String]): Unit = {
    val service = new com.ibeifeng.scala.service.MyService
    service.sayHello("leo")  
    service.sayHello("")  
  }
}

3.  package特性三:相对包名与绝对包名。

package com {
	package ibeifeng {
		package scala {
			object Utils {
				def isNotEmpty(str: String): Boolean = str != null && str != ""
			}
			
			class Test
			
			package collection {}
			
			package service {
				class MyService {
					// 默认使用相对报名,从com.ibeifeng.scala.collection包中,寻找mutable包下的ArrayBuffer类,但是找不到,所以会报错
					// val names = new scala.collection.mutable.ArrayBuffer[String]
					// 正确的做法是使用_root_,引用绝对包名
					val names = new _root_.scala.collection.mutable.ArrayBuffer[String]
					
					def sayHello(name: String) {
						if(Utils.isNotEmpty(name)) {
							println("Hello, " + name)
						} else {
							println("Who are you?")  
						}
					}
				}
			}
		}
	}
}

4.  package特性四:定义package对象
package内的成员,可以直接访问package对象内的成员。

package com.ibeifeng.scala

package object service {
	val defaultName = "Somebody"
}

package service {
	class MyService {
		def sayHello(name: String) {
			if(name != null && name != "") {
				println("Hello, " + name)
			} else {
				println("Hello, " + defaultName) 
			}
		}
	}
}

5.  package特性五:package可见性。

package com.ibeifeng.scala

class Person {
	private[scala] val name = "leo"
	private[ibeifeng] val age = 25
}

9、import

如果没有import,那么你每次创建某个包下的类的对象,都得用new com.ibeifeng.scala.service.MyService这种冗长的格式。所以如果用了import,那么,你只要先import com.ibeifeng.scala.service.MyService,然后再new MyService,即可。

import com.ibeifeng.scala.service.MyService;

object MainClass {
  def main(args: Array[String]): Unit = {
    val service = new MyService
    service.sayHello("leo")  
    service.sayHello("")  
  }
}

import的特性:
(1)import特性一:用import com.ibeifeng.scala.service._这种格式,可以导入包下所有的成员。
(2)import特性二:scala与java不同之处在于,任何地方都可以使用import,比如类内、方法内,这种方式的好处在于,可以在一定作用域范围内使用导入。

object MainClass {
  def main(args: Array[String]): Unit = {
    import com.ibeifeng.scala.service._
    
    val service = new MyService
    service.sayHello("leo")  
    service.sayHello("")  
  }
}

(3)import特性三:选择器、重命名、隐藏。

import com.ibeifeng.scala.service.{ MyService },仅仅导入java.awt包下的Color和Font类
import com.ibeifeng.scala.service.{ MyService => MyServiceImpl },将导入的类进行重命名
import com.ibeifeng.scala.service.{ MyService => _, _ },导入com.ibeifeng.scala.service包下所有的类,但是隐藏掉MyService类

(4)import特性四:隐式导入。
每个scala程序默认都会隐式导入以下几个包下所有的成员。

import java.lang._
import scala._
import Predef._
阅读更多

没有更多推荐了,返回首页