scala cook book-学习笔记

 

// https://www.oreilly.com/library/view/scala-cookbook/9781449340292/
CHAPTER 1  	String 字符串	
CHAPTER 2 	
CHAPTER 3 	
CHAPTER 4 	
CHAPTER 5 	
CHAPTER 6 	
CHAPTER 7 	
CHAPTER 8 	
CHAPTER 9 	


********************************************************Scala Cook Book*********************************************************
========================================================CP1 String 字符串
//1.1 Testing String Equallity 测试String相等性
scala> val a = "Marisa"					--->a: String = Marisa
scala> val b = "marisa"					--->b: String = marisa
scala> a.equalsIgnoreCase(b)				--->res0: Boolean = true  //equalsIgnoreCase 忽略大小写匹配相等性

//1.2. Creating Multiline Strings 
//stripMargin 去边方法
val speech = """Four score and 
|seven years ago""".stripMargin			//stripMargin方法

val speech = """Four score and
#seven years ago""".stripMargin('#')

scala> val speech = """Four score and
     | |seven years ago
     | |our fathers""".stripMargin.replaceAll("\n", " ")
		---->speech: String = Four score and seven years ago our fathers
replaceAll方法
scala> "zieox is a man".stripMargin.replaceAll(" ","-")				--->res0: String = zieox-is-a-man

//1.3. Splitting Strings
//split方法
scala> "hello world".split(" ")							--->res2: Array[String] = Array(hello, world)
scala> "hello world".split(" ").foreach(println)
--->	hello
	world
scala> val s = "eggs, milk, butter, Coco Puffs"					--->s: String = eggs, milk, butter, Coco Puffs
scala> s.split(",")					--->res3: Array[String] = Array(eggs, " milk", " butter", " Coco Puffs")
scala> s.split(",").map(_.trim)					--->res4: Array[String] = Array(eggs, milk, butter, Coco Puffs)

//1.4. Substituting Variables into Strings
//代入方法
scala> val name = "Fred"						--->name: String = Fred
scala> val age = 33							--->age: Int = 33
scala> val weight = 200.00						--->weight: Double = 200.0
scala> println(s"$name is $age years old, and weighs $weight pounds.")
									--->Fred is 33 years old, and weighs 200.0 pounds.
scala> println(s"Age next year: ${age + 1}")				--->Age next year: 34
scala> println(s"You are 33 years old: ${age == 33}")			--->You are 33 years old: true
scala> case class Student(name: String, score: Int)			--->defined class Student
scala> val hannah = Student("Hannah", 95)				--->hannah: Student = Student(Hannah,95)
scala> println(s"${hannah.name} has a score of ${hannah.score}")	--->Hannah has a score of 95
scala> println(s"$hannah.name has a score of $hannah.score")
								--->Student(Hannah,95).name has a score of Student(Hannah,95).score
// string println 的几种方法 by $ / .format
scala> val name = "Fred"						--->name: java.lang.String = Fred
scala> val age = 33							--->age: Int = 33
scala> val s = "%s is %d years old".format(name, age)			--->s: String = Fred is 33 years old
scala> println("%s is %d years old".format(name, age))			--->Fred is 33 years old

//Table 1-1. Common printf style format specifiers
-----------------------------------------------------------
Format specifier 	 Description
%c 			 Character
%d			 Decimal number (integer, base 10)
%e			 Exponential floating-point number
%f			 Floating-point number
%i			 Integer (base 10)
%o			 Octal number (base 8)
%s 			 A string of characters
%u			 Unsigned decimal (integer) number
%x			 Hexadecimal number (base 16)
%% 			 Print a “percent” character
\%			 Print a “percent” character
-----------------------------------------------------------

//1.5. Processing a String One Character at a Time
//toUpper 大写 & toLower 小写 & charAt 字符位置
scala> val upper = "hello, world".map(c => c.toUpper)			--->upper: String = HELLO, WORLD
scala> val upper = "hello, world".map(_.toUpper)			--->upper: String = HELLO, WORLD
scala> val upper = "hello, world".filter(_ != 'l').map(_.toUpper)	--->upper: String = HEO, WORD
scala> val result = for {c <- "hello, world";if c != 'l'} yield c.toUpper
scala> val upper = for (c <- "hello, world") yield c.toUpper		--->upper: String = HELLO, WORLD
String s = "Hello";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {char c = s.charAt(i)}
String result = sb.toString();

// first example
"HELLO".map(c => (c.toByte+32).toChar)
// second example
"HELLO".map{ c =>(c.toByte+32).toChar}

scala> def toLower(c: Char): Char = (c.toByte+32).toChar		--->toLower: (c: Char)Char
// use that method with map
scala> "HELLO".map(toLower)						--->res0: String = hello
scala> val s = "HELLO"							--->s: java.lang.String = HELLO
scala> for (c <- s) yield toLower(c)					--->res1: String = hello


object Adler32Checksum {
	val MOD_ADLER = 65521
	def main(args: Array[String]) {
		val sum = adler32sum("Wikipedia")
		printf("checksum (int) = %d\n", sum)
		printf("checksum (hex) = %s\n", sum.toHexString)
	}
	def adler32sum(s: String): Int = {
		var a = 1
		var b = 0
		s.getBytes.foreach{char =>
			a = (char + a) % MOD_ADLER
			b = (b + a) % MOD_ADLER
	}
	b * 65536 + a
	}
}

scala> "hello".getBytes							--->res0: Array[Byte] = Array(104, 101, 108, 108, 111)

//1.6. Finding Patterns in Strings 正则匹配String
scala> val numPattern = "[0-9]+".r					--->numPattern: scala.util.matching.Regex = [0-9]+
scala> val address = "123 Main Street Suite 101"			--->address: java.lang.String = 123 Main Street Suite 101
scala> val match1 = numPattern.findFirstIn(address)			--->match1: Option[String] = Some(123)
scala> val matches = numPattern.findAllIn(address)
							--->matches: scala.util.matching.Regex.MatchIterator = non-empty iterator
scala> matches foreach println				//matches生成的时iterator,所以通过foreach println 输出
	123
	101
//通过import Regex 方法生成
import scala.util.matching.Regex
scala> val matches = numPattern.findAllIn(address).toArray		--->matches: Array[String] = Array(123, 101)
scala> val numPattern = new Regex("[0-9]+")				--->numPattern: scala.util.matching.Regex = [0-9]+
scala> val address = "123 Main Street Suite 101"			--->address: java.lang.String = 123 Main Street Suite 101
scala> val match1 = numPattern.findFirstIn(address)			--->match1: Option[String] = Some(123)
scala> val address = "No address given"					--->address: String = No address given
scala> val match1 = numPattern.findFirstIn(address)			--->match1: Option[String] = None

//使用getOrElse
scala> val address = "123 Main Street Suite 101"
scala> val result = numPattern.findFirstIn(address).getOrElse("no match")		--->result: String = 123
match1 match {
	case Some(s) => println(s"Found: $s")
	case None =>
}
match1.foreach { e =>println(s"Found a match: $e")}


//1.7. Replacing Patterns in Strings 运用正则替换
//call replaceAll on a String:使用replaceAll(pattern,replaceTo)
scala> val address = "123 Main Street".replaceAll("[0-9]", "x")			--->address: java.lang.String = xxx Main Street
//regex.replaceAllIn(String,replaceTo)
scala> val regex = "[0-9]".r							--->regex: scala.util.matching.Regex = [0-9]
scala> val newAddress = regex.replaceAllIn("123 Main Street", "x")		--->newAddress: String = xxx Main Street
//replaceFirst(Regex,replaceTo)
scala> val result = "123".replaceFirst("[0-9]", "x")				--->result: java.lang.String = x23
scala> val regex = "H".r							--->regex: scala.util.matching.Regex = H
scala> val result = regex.replaceFirstIn("Hello world", "J")			--->result: String = Jello world
//pattern实例
scala> val pattern = "([0-9]+) ([A-Za-z]+)".r				--->pattern: scala.util.matching.Regex = ([0-9]+) ([A-Za-z]+)
scala> val pattern(count, fruit) = "100 Bananas"
	count: String = 100
	fruit: String = Bananas


//an Example
"movies near 80301"
"movies 80301"
"80301 movies"
"movie: 80301"
"movies: 80301"
"movies near boulder, co"
"movies near boulder, colorado"

val MoviesZipRE = "movies (\\d{5})".r						// match "movies 80301"
val MoviesNearCityStateRE = "movies near ([a-z]+), ([a-z]{2})".r		// match "movies near boulder, co"

textUserTyped match {
	case MoviesZipRE(zip) => getSearchResults(zip)
	case MoviesNearCityStateRE(city, state) => getSearchResults(city, state)
	case _ => println("did not match a regex")
}

//1.9. Accessing a Character in a String:取出String中字符
scala> "hello".charAt(0)					--->res0: Char = h
scala> "hello"(0)						--->res1: Char = h
scala> "hello"(1)						--->res2: Char = e
scala> "hello"(1)						--->res0: Char = e
scala> "hello".apply(1)						--->res1: Char = e

//1.10. Add Your Own Methods to the String Class:给String class添加自有方法
implicit class StringImprovements(s: String) {def increment = s.map(c => (c + 1).toChar)}
scala> val result = "HAL".increment				--->result: String = IBM
//Put the implicit class in an object
package com.alvinalexander.utils
object StringUtils {implicit class StringImprovements(val s: String) {def increment = s.map(c => (c + 1).toChar)}}
package foo.bar
import com.alvinalexander.utils.StringUtils._
object Main extends App {println("HAL".increment)}

//Put the implicit class in a package object
package com.alvinalexander
package object utils {implicit class StringImprovements(val s: String) {def increment = s.map(c => (c + 1).toChar)}}
package foo.bar
import com.alvinalexander.utils._
object MainDriver extends App {println("HAL".increment)}

//
class StringImprovements(val s: String) {def increment = s.map(c => (c + 1).toChar)}
implicit def stringToString(s: String) = new StringImprovements(s)
"HAL".increment

//Annotate your method return type
implicit class StringImprovements(val s: String) {
	def increment = s.map(c => (c + 1).toChar)
	def decrement = s.map(c => (c - 1).toChar)
	def hideAll = s.replaceAll(".", "*")
}


//Returning other types
implicit class StringImprovements(val s: String) {
	def increment = s.map(c => (c + 1).toChar)
	def decrement = s.map(c => (c - 1).toChar)
	def hideAll: String = s.replaceAll(".", "*")
	def plusOne = s.toInt + 1
	def asBoolean = s match {
		case "0" | "zero" | "" | " " => false
		case _ => true
	}
}

scala> "4".plusOne				--->res0: Int = 5
scala> "0".asBoolean				--->res1: Boolean = false
scala> "1".asBoolean				--->res2: Boolean = true

========================================================CP2 Numbers 数字
Table 2-1. Data ranges of Scala’s built-in numeric types
---------------------------------------------------------------
Data type 		Range
Char 			16-bit unsigned Unicode character
Byte	 		8-bit signed value
Short 			16-bit signed value
Int 			32-bit signed value
Long 			64-bit signed value
Float 			32-bit IEEE 754 single precision float
Double 			64-bit IEEE 754 single precision float
---------------------------------------------------------------
scala> Short.MinValue				--->res0: Short = −32768
scala> Short.MaxValue				--->res1: Short = 32767

//2.1. Parsing a Number from a String
scala> "100".toInt				--->res0: Int = 100
scala> "100".toDouble				--->res1: Double = 100.0
scala> "100".toFloat				--->res2: Float = 100.0
scala> "1".toLong				--->res3: Long = 1
scala> "1".toShort				--->res4: Short = 1
scala> "1".toByte				--->res5: Byte = 1
scala> val b = BigInt("1")			--->b: scala.math.BigInt = 1
scala> val b = BigDecimal("3.14159")		--->b: scala.math.BigDecimal = 3.14159

//Handling a base and radix
scala> Integer.parseInt("1", 2)			--->res0: Int = 1
scala> Integer.parseInt("10", 2)		--->res1: Int = 2
scala> Integer.parseInt("100", 2)		--->res2: Int = 4
scala> Integer.parseInt("1", 8)			--->res3: Int = 1
scala> Integer.parseInt("10", 8)		--->res4: Int = 8
//隐式转换
implicit class StringToInt(s: String) {def toInt(radix: Int) = Integer.parseInt(s, radix)}
scala> "1".toInt(2)				--->res0: Int = 1
scala> "10".toInt(2)				--->res1: Int = 2
scala> "100".toInt(2)				--->res2: Int = 4
scala> "100".toInt(8)				--->res3: Int = 64
scala> "100".toInt(16)				--->res4: Int = 256

//手写toInt
def toInt(s: String):Option[Int] = {
	try {Some(s.toInt)}
	catch {case e: NumberFormatException => None}
}
println(toInt("1").getOrElse(0))
println(toInt("a").getOrElse(0))
val x = toInt(aString).getOrElse(0)
toInt(aString) match {
	case Some(n) => println(n)
	case None => println("Boom! That wasn't a number.")
}
val result = toInt(aString) match {
	case Some(x) => x
	case None => 0 // however you want to handle this
}

//2.2. Converting Between Numeric Types (Casting) 数子转换
scala> val b = a.to[Tab]
 toByte		toChar		toDouble
 toShort	toString	toFloat
 toInt		toLong
scala> 19.45.toInt				--->res0: Int = 19
scala> 19.toFloat				--->res1: Float = 19.0
scala> 19.toDouble				--->res2: Double = 19.0
scala> 19.toLong				--->res3: Long = 19
scala> val a = 1000L				--->a: Long = 1000
scala> a.isValidByte				--->res0: Boolean = false
scala> a.isValidShort				--->res1: Boolean = true

//2.3. Overriding the Default Numeric Type 重写数字类型
scala> val a = 1d				--->a: Double = 1.0
scala> val a = 1f				--->a: Float = 1.0
scala> val a = 1000L				--->a: Long = 1000
scala> val a = 0: Byte				--->a: Byte = 0
scala> val a = 0: Int				--->a: Int = 0
scala> val a = 0: Short				--->a: Short = 0
scala> val a = 0: Double			--->a: Double = 0.0
scala> val a = 0: Float				--->a: Float = 0.0
scala> val a = 0x20				--->a: Int = 32
// if you want to store the value as a Long
scala> val a = 0x20L				--->a: Long = 32
class Foo {
	var a: Short = 0
	var b: Short = _ /* defaults to 0*/
}

//2.4. Replacements for ++ and −−
scala> var a = 1				--->aa: Int = 1
scala> a += 1
scala> println(a)				--->a2
scala> a −= 1
scala> println(a)				--->a1
scala> var i = 1				--->ai: Int = 1
scala> i *= 2
scala> println(i)				--->a2
scala> i *= 2
scala> println(i)				--->a4
scala> i /= 2
scala> println(i)				--->a2
scala> var x = 1d				--->x: Double = 1.0
scala> x += 1
scala> println(x)				--->2.0
scala> var x = 1f				--->x: Float = 1.0
scala> x += 1
scala> println(x)				--->2.0

//2.5. Comparing Floating-Point Numbers
def ~=(x: Double, y: Double, precision: Double) = {if ((x - y).abs < precision) true else false}

scala> val a = 0.3				--->a: Double = 0.3
scala> val b = 0.1 + 0.2			--->b: Double = 0.30000000000000004
scala> ~=(a, b, 0.0001)				--->res0: Boolean = true
scala> ~=(b, a, 0.0001)				--->res1: Boolean = true

object MathUtils {def ~=(x: Double, y: Double, precision: Double) = {if ((x - y).abs < precision) true else false}}
println(MathUtils.~=(a, b, 0.000001))

//2.6. Handling Very Large Numbers (处理大数字)
scala> var b = BigInt(1234567890)		--->b: scala.math.BigInt = 1234567890
scala> var b = BigDecimal(123456.789)		--->b: scala.math.BigDecimal = 123456.789
scala> b + b					--->res0: scala.math.BigInt = 2469135780
scala> b * b					--->res1: scala.math.BigInt = 1524157875019052100
scala> b += 1
scala> println(b)				--->1234567891
scala> b.toInt					--->res2: Int = 1234567891
scala> b.toLong					--->res3: Long = 1234567891
scala> b.toFloat				--->res4: Float = 1.23456794E9
scala> b.toDouble				--->res5: Double = 1.234567891E9
scala> b.isValidByte				--->res6: Boolean = false
scala> b.isValidChar				--->res7: Boolean = false
scala> b.isValidShort				--->res8: Boolean = false
scala> if (b.isValidInt) b.toInt		--->res9: AnyVal = 1234567890
scala> Byte.MaxValue				--->res0: Byte = 127
scala> Short.MaxValue				--->res1: Short = 32767
scala> Int.MaxValue				--->res2: Int = 2147483647
scala> Long.MaxValue				--->res3: Long = 9223372036854775807
scala> Double.PositiveInfinity			--->res0: Double = Infinity
scala> Double.NegativeInfinity			--->res1: Double = -Infinity
scala> 1.7976931348623157E308 > Double.PositiveInfinity			--->res45: Boolean = false

//2.7. Generating Random Numbers (生成随机数)
val r = scala.util.Random
scala> r.nextInt				--->res0: Int = −1323477914
scala> r.nextInt(100)				--->res1: Int = 58

scala> r.nextFloat				--->res2: Float = 0.50317204
// returns a value between 0.0 and 1.0
scala> r.nextDouble				--->res3: Double = 0.6946000981900997
scala> val r = new scala.util.Random(100)	--->r: scala.util.Random = scala.util.Random@bbf4061

//产生随机字母
scala> r.nextPrintableChar			--->res0: Char = H
var range = 0 to r.nextInt(10)
//随机range
scala> var range = 0 to r.nextInt(10)
		--->range: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3)
scala> range = 0 to r.nextInt(10)
		--->range: scala.collection.immutable.Range.Inclusive = Range(0, 1)
scala> for (i <- 0 to r.nextInt(10)) yield i * 2
		--->res1: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 2, 4, 6)
scala> for (i <- 0 to r.nextInt(10)) yield (i * r.nextFloat)
		--->res1: scala.collection.immutable.IndexedSeq[Float] =Vector(0.0, 0.71370363, 1.0783684)
//随机生成字符
scala> for (i <- 0 to r.nextInt(10)) yield r.nextPrintableChar
		--->res4: scala.collection.immutable.IndexedSeq[Char] = Vector(Z, ?, R)
//生成一组5个随机值
val a = for (i <- 1 to 5) yield r.nextInt(100)

//2.8. Creating a Range, List, or Array of Numbers 生成range
for (i <- 1 to 15 by 3) println(i)			--->[1,15] by 3
for (i <- 1 until 5) println(i)				--->[1,5)

val x = (1 to 10).toArray
scala> var range = 0 to scala.util.Random.nextInt(10)
		--->range: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3)
scala> for (i <- 1 to 5) yield i.toDouble
			--->res0: scala.collection.immutable.IndexedSeq[Double] = Vector(1.0, 2.0, 3.0, 4.0, 5.0)

//2.9. Formatting Numbers and Currency 关于数字的格式化
scala> val pi = scala.math.Pi				--->pi: Double = 3.141592653589793
//保留五位小数
scala> println(f"$pi%1.5f")				--->3.14159
scala> f"$pi%1.2f"					--->res1: String = 3.14
scala> f"$pi%06.2f"					--->res2: String = 003.14
scala> "%06.2f".format(pi)				--->res3: String = 003.14

scala> val formatter = java.text.NumberFormat.getIntegerInstance
		--->formatter: java.text.NumberFormat = java.text.DecimalFormat@674dc
scala> formatter.format(10000)				--->res0: String = 10,000
scala> formatter.format(1000000)			--->res1: String = 1,000,000

scala> val locale = new java.util.Locale("de", "DE")		--->locale: java.util.Locale = de_DE
scala> val formatter = java.text.NumberFormat.getIntegerInstance(locale)
		--->formatter: java.text.NumberFormat = java.text.DecimalFormat@674dc
scala> formatter.format(1000000)				--->res2: String = 1.000.000

scala> val formatter = java.text.NumberFormat.getInstance
		--->formatter: java.text.NumberFormat = java.text.DecimalFormat@674dc
scala> formatter.format(10000.33)				--->res0: String = 10,000.33

scala> val formatter = java.text.NumberFormat.getCurrencyInstance
		--->formatter: java.text.NumberFormat = java.text.DecimalFormat@67500
scala> println(formatter.format(123.456789))			--->$123.46
scala> println(formatter.format(1234.56789))			--->$1,234.57
scala> println(formatter.format(12345.6789))			--->$12,345.68
scala> println(formatter.format(123456.789))			--->$123,456.79

scala> import java.util.{Currency, Locale}			--->import java.util.{Currency, Locale}
scala> val de = Currency.getInstance(new Locale("de", "DE"))	--->de: java.util.Currency = EUR
scala> formatter.setCurrency(de)
scala> println(formatter.format(123456.789))			---->EUR123,456.79



========================================================CP3 Control Structures 控制结构
//if else 
val x = if (a) y else z
//for 
for (line <- source.getLines) {
	for{char <- line;if char.isLetter} 
	// char algorithm here ...
}
val nieces = List("emily", "hannah", "mercedes", "porsche")
scala> for (n <- nieces) yield n.capitalize			//首字母大写
		--->res14: List[String] = List(Emily, Hannah, Mercedes, Porsche)

//3.1. Looping with for and foreach (foreach 循环)
val a = Array("apple", "banana", "orange")
//toUpperCase示例
for (i<-a){val s = i.toUpperCase;println(s)}
val newArray = for (e <- a) yield e.toUpperCase
a map(_.toUpperCase) foreach println
val newArray = for (e <- a) yield {val s = e.toUpperCase;s}
				--->newArray: Array[String] = Array(APPLE, BANANA, ORANGE)

for (i <- 0 until a.length) {println(s"$i is ${a(i)}")}
			--->0 is apple
			    1 is banana
			    2 is orange
for ((e, count) <- a.zipWithIndex) {println(s"$count is $e")}
			--->0 is apple
			    1 is banana
			    2 is orange

//for-if (遍历map)
for (i <- 1 to 10 if i < 4) println(i)
//Looping over a Map
val names = Map("fname" -> "Robert","lname" -> "Goren")
for ((k,v) <- names) println(s"key: $k, value: $v")

a.foreach(e => println(e.toUpperCase))
1.to(10).foreach(((i) => println(i)))
1.to(10).withFilter(((i) => i.$percent(2).$eq$eq(0))).foreach(((i) => println(i)))

for {i <- 1 to 10 ; if i != 1 ; if i % 2 == 0} println(i)

//3.2. Using for Loops with Multiple Counters
//创建二维数组 (多维数组)
val array =Array.ofDim[Int](2,2)

//3.3. Using a for Loop with Embedded if Statements (for - if )
for (file <- files) {if (hasSoundFileExtension(file) && !soundFileIsLong(file)) {soundFiles += file}}

for {file <- files;if passesFilter1(file);if passesFilter2(file)} doSomething(file)

//3.4. Creating a for Comprehension (for/yield Combination)
val names = Array("chris", "ed", "maurice")
val capNames = for (e <- names) yield e.capitalize
var fruits = scala.collection.mutable.ArrayBuffer[String]()
fruits += "apple"
fruits += "banana"
fruits += "orange"
val fruits = "apple" :: "banana" :: "orange" :: Nil
val out = for (e <- fruits) yield e.toUpperCase
val out = fruits.map(_.toUpperCase)

//3.5. Implementing break and continue (使用break和continue)
import util.control.Breaks._
object BreakAndContinueDemo extends App {
	println("\n=== BREAK EXAMPLE ===")
	breakable {for (i <- 1 to 10) {println(i);if (i > 4) break}}
	println("\n=== CONTINUE EXAMPLE ===")
	val searchMe = "peter piper picked a peck of pickled peppers"
	var numPs = 0
	for (i <- 0 until searchMe.length) {breakable { if (searchMe.charAt(i) != 'p') {break} else {numPs += 1} }}
	println("Found " + numPs + " p's in the string.")
}

private val breakException = new BreakControl
def break(): Nothing = { throw breakException }
def breakable(op: => Unit) {
	try {op} 
	catch {case ex: BreakControl => if (ex ne breakException) throw ex}
}

//
val searchMe = "peter piper picked a peck of pickled peppers"
var numPs = 0
for (i <- 0 until searchMe.length) {
	breakable {
		if (searchMe.charAt(i) != 'p') {break}
		else {numPs += 1}
	}
}
println("Found " + numPs + " p's in the string.")

//break
//To implement a break, this Scala:
breakable {for (x <- xs) {if (cond)break}}
//corresponds to this Java:
for (X x : xs) {if (cond) break;}
//continue
//To implement continue functionality, this Scala:
for (x <- xs) {breakable {if (cond)break}}
//corresponds to this Java:
for (X x : xs) {if (cond) continue;}

val count = searchMe.count(_ == 'p')


//
package com.alvinalexander.labeledbreaks
object LabeledBreakDemo extends App {
	import scala.util.control._
	val Inner = new Breaks
	val Outer = new Breaks
	Outer.breakable {
		for (i <- 1 to 5) {
			Inner.breakable {
				for (j <- 'a' to 'e') {
					if (i == 1 && j == 'c') Inner.break else println(s"i: $i, j: $j")
					if (i == 2 && j == 'b') Outer.break
				}
			}
		}
	}
}

import scala.util.control._
val Exit = new Breaks
Exit.breakable {for (j <- 'a' to 'e') {if (j == 'c') Exit.break else println(s"j: $j")}}


var barrelIsFull = false
for (monkey <- monkeyCollection if !barrelIsFull) {
	addMonkeyToBarrel(monkey)
	barrelIsFull = checkIfBarrelIsFull
}

def sumToMax(arr: Array[Int], limit: Int): Int = {
	var sum = 0
	for (i <- arr) {sum += i ; if (sum > limit) return limit}
	sum
}
val a = Array.range(0,10)
println(sumToMax(a, 10))


// 实现一个阶层函数 n*(n-1)(n-2)...*1
def factorial(n: Int): Int = {
	if (n == 1) 1
	else n * factorial(n - 1)
}

import scala.annotation.tailrec
def factorial(n: Int): Int = {
	@tailrec 
	def factorialAcc(acc: Int, n: Int): Int = {if (n <= 1) acc ; else factorialAcc(n * acc, n - 1)}
	factorialAcc(1, n)
}


//3.6. Using the if Construct Like a Ternary Operator (使用if)
val absValue = if (a < 0) -a else a
println(if (i == 0) "a" else "b")
hash = hash * prime + (if (name == null) 0 else name.hashCode)


def abs(x: Int) = if (x >= 0) x else -x
def max(a: Int, b: Int) = if (a > b) a else b
val c = if (a > b) a else b


//3.7. Using a Match Expression Like a switch Statement (使用match表达式)
def tes(i:Int)=
i match {
	case 1 => println("January")
	case 2 => println("February")
	case 3 => println("March")
	case 4 => println("April")
	case 5 => println("May")
	case 6 => println("June")
	case 7 => println("July")
	case 8 => println("August")
	case 9 => println("September")
	case 10 => println("October")
	case 11 => println("November")
	case 12 => println("December")
	// catch the default with a variable so you can print it
	case whoa => println("Unexpected case: " + whoa.toString)
}


//使用switch
import scala.annotation.switch
class SwitchDemo {
	val i = 1
	val x = (i: @switch) match {
		case 1 => "One"
		case 2 => "Two"
		case _ => "Other"
	}
}


def getClassAsString(x: Any): String = x match {
	case s: String => s + " is a String"
	case i: Int => "Int"
	case f: Float => "Float"
	case l: List[_] => "List"
	case p: Person => "Person"
	case _ => "Unknown"
}


val monthNumberToName = Map(
	1 -> "January",
	2 -> "February",
	3 -> "March",
	4 -> "April",
	5 -> "May",
	6 -> "June",
	7 -> "July")
val monthName = monthNumberToName(4)
println(monthName) // prints "April"


//3.8. Matching Multiple Conditions with One Case Statement
val i = 5
i match {
	case 1 | 3 | 5 | 7 | 9 => println("odd")
	case 2 | 4 | 6 | 8 | 10 => println("even")
}
val cmd = "stop"
cmd match {
	case "start" | "go" => println("starting")
	case "stop" | "quit" | "exit" => println("stopping")
	case _ => println("doing nothing")
}

trait Command
case object Start extends Command
case object Go extends Command
case object Stop extends Command
case object Whoa extends Command
def executeCommand(cmd: Command) = cmd match {
	case Start | Go => start()
	case Stop | Whoa => stop()
}


//3.9. Assigning the Result of a Match Expression to a Variable
val evenOrOdd = someNumber match {
	case 1 | 3 | 5 | 7 | 9 => println("odd")
	case 2 | 4 | 6 | 8 | 10 => println("even")
}
def isTrue(a: Any) = a match {
	case 0 | "" => false
	case _ => true
}

//3.10. Accessing the Value of the Default Case in a Match Expression(使用default case-default)
i match {
	case 0 => println("1")
	case 1 => println("2")
	case default => println("You gave me: " + default)
}

//3.11. Using Pattern Matching in Match Expressions (正则匹配)
ex:case匹配
def echoWhatYouGaveMe(x: Any): String = x match {
// constant patterns
	case 0 => "zero"
	case true => "true"
	case "hello" => "you said 'hello'"
	case Nil => "an empty List"
// sequence patterns
	case List(0, _, _) => "a three-element list with 0 as the first element"
	case List(1, _*) => "a list beginning with 1, having any number of elements"
	case Vector(1, _*) => "a vector starting with 1, having any number of elements"
// tuples
	case (a, b) => s"got $a and $b"
	case (a, b, c) => s"got $a, $b, and $c"
// constructor patterns
	case Person(first, "Alexander") => s"found an Alexander, first name = $first"
	case Dog("Suka") => "found a dog named Suka"
// typed patterns
	case s: String => s"you gave me this string: $s"
	case i: Int => s"thanks for the int: $i"
	case f: Float => s"thanks for the float: $f"
	case a: Array[Int] => s"an array of int: ${a.mkString(",")}"
	case as: Array[String] => s"an array of strings: ${as.mkString(",")}"
	case d: Dog => s"dog: ${d.name}"
	case list: List[_] => s"thanks for the List: $list"
	case m: Map[_, _] => m.toString
// the default wildcard pattern
	case _ => "Unknown"
}


object LargeMatchTest extends App {
	case class Person(firstName: String, lastName: String)
	case class Dog(name: String)
// trigger the constant patterns
	println(echoWhatYouGaveMe(0))
	println(echoWhatYouGaveMe(true))
	println(echoWhatYouGaveMe("hello"))
	println(echoWhatYouGaveMe(Nil))
// trigger the sequence patterns
	println(echoWhatYouGaveMe(List(0,1,2)))
	println(echoWhatYouGaveMe(List(1,2)))
	println(echoWhatYouGaveMe(List(1,2,3)))
	println(echoWhatYouGaveMe(Vector(1,2,3)))
// trigger the tuple patterns
	println(echoWhatYouGaveMe((1,2)))
	println(echoWhatYouGaveMe((1,2,3)))
// two element tuple
// three element tuple
// trigger the constructor patterns
	println(echoWhatYouGaveMe(Person("Melissa", "Alexander")))
	println(echoWhatYouGaveMe(Dog("Suka")))
// trigger the typed patterns
	println(echoWhatYouGaveMe("Hello, world"))
	println(echoWhatYouGaveMe(42))
	println(echoWhatYouGaveMe(42F))
	println(echoWhatYouGaveMe(Array(1,2,3)))
	println(echoWhatYouGaveMe(Array("coffee", "apple pie")))
	println(echoWhatYouGaveMe(Dog("Fido")))
	println(echoWhatYouGaveMe(List("apple", "banana")))
	println(echoWhatYouGaveMe(Map(1->"Al", 2->"Alexander")))
// trigger the wildcard pattern
	println(echoWhatYouGaveMe("33d"))
}


case list: List[_] => s"thanks for the List: $list"
case m: Map[_, _] => m.toString
case m: Map[a, b] => m.toString
case list: List[x] => s"thanks for the List: $list"

import java.io.File
sealed trait RandomThing
case class RandomFile(f: File) extends RandomThing
case class RandomString(s: String) extends RandomThing
class RandomNoiseMaker {
	def makeRandomNoise(t: RandomThing) = t match {
		case RandomFile(f) => playSoundFile(f)
		case RandomString(s) => speak(s)
	}
}


case class Person(firstName: String, lastName: String)
object Test2 extends App {
	def matchType(x: Any): String = x match {
//case x: List(1, _*) => s"$x" // doesn't compile
	case x @ List(1, _*) => s"$x"
// works; prints the list
//case Some(_) => "got a Some" // works, but can't access the Some
//case Some(x) => s"$x" // works, returns "foo"
	case x @ Some(_) => s"$x"
// works, returns "Some(foo)"
	case p @ Person(first, "Doe") => s"$p"
// works, returns "Person(John,Doe)"
	}
	println(matchType(List(1,2,3)))
	println(matchType(Some("foo")))
	println(matchType(Person("John", "Doe")))
// prints "List(1, 2, 3)"
// prints "Some(foo)"
// prints "Person(John,Doe)"
}


//Using Some and None in match expressions (match-Option)
def toInt(s: String): Option[Int] = {
	try {Some(Integer.parseInt(s.trim))}
	catch {case e: Exception => None}
}

toInt("42") match {
	case Some(i) => println(i)
	case None => println("That wasn't an Int.")
}


//3.12. Using Case Classes in Match Expressions 
trait Animal
case class Dog(name: String) extends Animal
case class Cat(name: String) extends Animal
case object Woodpecker extends Animal
object CaseClassTest extends App {
	def determineType(x: Animal): String = x match {
		case Dog(moniker) => "Got a Dog, name = " + moniker
		case _:Cat => "Got a Cat (ignoring the name)"
		case Woodpecker => "That was a Woodpecker"
		case _ => "That was something else"
	}
	println(determineType(new Dog("Rocky")))
	println(determineType(new Cat("Rusty the Cat")))
	println(determineType(Woodpecker))
}

//3.13. Adding if Expressions (Guards) to Case Statements  (case-if)

i match {
	case a if 0 to 9 contains a => println("0-9 range: " + a)
	case b if 10 to 19 contains b => println("10-19 range: " + b)
	case c if 20 to 29 contains c => println("20-29 range: " + c)
	case _ => println("Hmmm...")
}

//Use it to match different values of an object:
num match {
	case x if x == 1 => println("one, a lonely number")
	case x if (x == 2 || x == 3) => println(x)
	case _ => println("some other value")
}

stock match{
	case x if (x.symbol == "XYZ" && x.price < 20) => buy(x)
	case x if (x.symbol == "XYZ" && x.price > 50) => sell(x)
	case _ => // do nothing
}
scala> case class Person(name:String,age:Int)			--->defined class Person
scala> val j=new Person("jack",11)				--->j: Person = Person(jack,11)
scala> val z=new Person("zieox",22)				--->z: Person = Person(zieox,22)
def speak(p: Person) = p match{
	case Person(name,_) if name == "zieox" => println("Yubba dubba doo")
	case Person(name,_) if name == "Bam Bam" => println("Bam bam!")
	case _ => println("Watch the Flintstones!")
}
scala> speak(j)			--->Watch the Flintstones!
scala> speak(z)			--->Yubba dubba doo

//3.14. Using a Match Expression Instead of isInstanceOf (使用match匹配)
def isPerson(x: Any): Boolean = x match {case p: Person => true;case _ => false}

trait SentientBeing
trait Animal extends SentientBeing
case class Dog(name: String) extends Animal
case class Person(name: String, age: Int) extends SentientBeing
def printInfo(x: SentientBeing) = x match {
	case Person(name, age) => println(name)		// handle the Person
	case Dog(name) => println(name)			// handle the Dog
}

//3.15. Working with a List in a Match Expression (在list中哦使用match表达式) 
val x = List(1, 2, 3)
val y = 1 :: 2 :: 3 :: Nil

def listToString(list: List[String]): String = list match {
	case s :: rest => s + " " + listToString(rest)
	case Nil => ""
}
//用match实现sum函数
def sum(list: List[Int]): Int = list match {
	case Nil => 1
	case n :: rest => n + sum(rest)
}
//用match实现multiply函数
def multiply(list: List[Int]): Int = list match {
	case Nil => 1
	case n :: rest => n * multiply(rest)
}

//3.16. Matching One or More Exceptions with try/catch (try catch)
val s = "Foo"
try {val i = s.toInt} catch {case e: Exception => e.printStackTrace}

try {openAndReadAFile(filename)} catch {
	case e: FileNotFoundException => println("Couldn't find that file.")
	case e: IOException => println("Had an IOException trying to read that file")
}

try {openAndReadAFile("foo")} catch {case t: Throwable => t.printStackTrace()}
try {val i = s.toInt} catch {case _: Throwable => println("exception ignored")}
def toInt(s: String): Option[Int] = try {Some(s.toInt)} catch {case e: Exception => throw e}

@throws(classOf[NumberFormatException])
def toInt(s: String): Option[Int] =
try {Some(s.toInt)} catch {case e: NumberFormatException => throw e}


//3.17. Declaring a Variable Before Using It in a try/catch/finally Block (在使用try/catch/finally 时声明可变)
import java.io._
object CopyBytes extends App {
	var in = None: Option[FileInputStream]
	var out = None: Option[FileOutputStream]
	try {
		in = Some(new FileInputStream("/tmp/Test.class"))
		out = Some(new FileOutputStream("/tmp/Test.class.copy"))
		var c = 0
		while ({c = in.get.read; c != −1}) {out.get.write(c)}
	} 
	catch {case e: IOException => e.printStackTrace}
	finally {
	println("entered finally ...")
	if (in.isDefined) in.get.close
	if (out.isDefined) out.get.close
	}
}

//
try {
	in = Some(new FileInputStream("/tmp/Test.class"))
	out = Some(new FileOutputStream("/tmp/Test.class.copy"))
	in.foreach { inputStream =>
		out.foreach { outputStream =>
			var c = 0
			while ({c = inputStream.read; c != −1}) {outputStream.write(c)}
		}
	}
}
var in = None: Option[FileInputStream]
var out = None: Option[FileOutputStream]
var x = None: Option[Type]

//
var store: Store = null
var inbox: Folder = null
try {
// (2) use the variables/fields in the try block
	store = session.getStore("imaps")
	inbox = getFolder(store, "INBOX")
// rest of the code here ...
catch {
	case e: NoSuchProviderException => e.printStackTrace
	case me: MessagingException => me.printStackTrace
} 
finally {
// (3) call close() on the objects in the finally clause
	if (inbox != null) inbox.close
	if (store != null) store.close
}

//3.18. Creating Your Own Control Structures (建立你自己的控制结构)
package foo
import com.alvinalexander.controls.Whilst._
object WhilstDemo extends App {
	var i = 0
	whilst (i < 5) {
		println(i)
		i += 1
	}
}
//**
def whilst(testCondition: => Boolean)(codeBlock: => Unit) {while (testCondition) {codeBlock}}

package com.alvinalexander.controls
import scala.annotation.tailrec
object Whilst {
// 2nd attempt
@tailrec
	def whilst(testCondition: => Boolean)(codeBlock: => Unit) {
		if (testCondition) {
			codeBlock
			whilst(testCondition)(codeBlock)
		}
	}
}
//**
doubleif(age > 18)(numAccidents == 0) { println("Discount!") }
def doubleif(test1: => Boolean)(test2: => Boolean)(codeBlock: => Unit) {if (test1 && test2) {codeBlock}}



========================================================CP4 Classes and Properties (类和构造函数)
//4.1. Creating a Primary Constructor
class Person(var firstName: String, var lastName: String) {
	println("the constructor begins")
// some class fields
	private val HOME = System.getProperty("user.home")	//获取userhome 用户目录
	var age = 0
// some methods
	override def toString = s"$firstName $lastName is $age years old"
	def printHome { println(s"HOME = $HOME") }
	def printFullName { println(this) } // uses toString
	printHome
	printFullName
	println("still in the constructor")
}

//by java
public Person(String firstName, String lastName){
	super();
	this.firstName = firstName;
	this.lastName = lastName;
	Predef$.MODULE$.println("the constructor begins");
	age = 0;
	printHome();
	printFullName();
	Predef$.MODULE$.println("still in the constructor");
}

//Another comparison with Java
public class Person {
	private String firstName;
	private String lastName;
	private final String HOME = System.getProperty("user.home");
	private int age;
	public Person(String firstName, String lastName) {
		super();
		this.firstName = firstName;
		this.lastName = lastName;
		System.out.println("the constructor begins");
		age = 0;
		printHome();
		printFullName();
		System.out.println("still in the constructor");
	}
	public String firstName() { return firstName; }
	public String lastName() { return lastName; }
	public int age() { return age; }
	public void firstName_$eq(String firstName) {this.firstName = firstName;}
	public void lastName_$eq(String lastName) {this.lastName = lastName;}
	public void age_$eq(int age) {this.age = age;}
	public String toString() {return firstName + " " + lastName + " is " + age + " years old";}
	public void printHome() {System.out.println(HOME);}
	public void printFullName() {System.out.println(this);}
}
object Test extends App {
	val p = new Person
// the 'normal' mutator approach
	p.name = "Ron Artest"
	println(p)
// the 'hidden' mutator method
	p.name_$eq("Metta World Peace")
	println(p)
}

//4.2. Controlling the Visibility of Constructor Fields	(控制结构域)
//class by var 
class Person(var name: String)
val p = new Person("Alvin Alexander")
// getter
scala> p.name						--->res0: String = Alvin Alexander
// setter
scala> p.name = "Fred Flintstone"			--->p.name: String = Fred Flintstone
scala> p.name						--->res1: String = Fred Flintstone
//calss by val 
class Person(val name: String)
val p = new Person("Alvin Alexander")			--->p: Person = Person@3f9f332b
scala> p.name						--->res0: String = Alvin Alexander
scala> p.name = "Fred Flintstone"			---><console>:11: error: reassignment to

class Person(name: String)
scala> val p = new Person("Alvin Alexander")		--->p: Person = Person@144b6a6c
scala> p.name						--->error

---------------------------------------------------------------------------------
Table 4-1. The effect of constructor parameter settings(var val private 的可见性)
Visibility					Accessor?	Mutator?
var						Yes		Yes
val 						Yes		No
Default visibility (no var or val )		No		No
Adding the private keyword to var or val	No		No
---------------------------------------------------------------------------------

//Case classes 实例类
case class Person(name: String)
scala> val p = Person("Dale Cooper")			--->p: Person = Person(Dale Cooper)
scala> p.name						--->res0: String = Dale Cooper
# 在普通类中by var 可以修改,而 val 不行 ,class 中非以字段传入的参数不能直接调出
# 而在实例类中则可以直接 (.)调出


//4.3. Defining Auxiliary Constructors (定义伴生对象)
//关于伴生对象,伴生类:		https://www.cnblogs.com/nethk/p/5609320.html

// primary constructor
class Pizza (var crustSize: Int, var crustType: String) {
// one-arg auxiliary constructor
	def this(crustSize: Int) {this(crustSize, Pizza.DEFAULT_CRUST_TYPE)}
// one-arg auxiliary constructor
	def this(crustType: String) {this(Pizza.DEFAULT_CRUST_SIZE, crustType)}
// zero-arg auxiliary constructor
	def this() {this(Pizza.DEFAULT_CRUST_SIZE, Pizza.DEFAULT_CRUST_TYPE)}
	override def toString = s"A $crustSize inch pizza with a $crustType crust"
}
object Pizza {
	val DEFAULT_CRUST_SIZE = 12
	val DEFAULT_CRUST_TYPE = "THIN"
}

val p1 = new Pizza(Pizza.DEFAULT_CRUST_SIZE,Pizza.DEFAULT_CRUST_TYPE)
val p2 = new Pizza(Pizza.DEFAULT_CRUST_SIZE)
val p3 = new Pizza(Pizza.DEFAULT_CRUST_SIZE)
val p4 = new Pizza

//exercise: 写一个伴生对象
class spuerman(var name:String,var age:Int ){
	def this(name:String){this(name,spuerman.age)}	//传入name参数
	def this(age:Int){this(spuerman.name,age)}	//传入age参数
	def this() {this(spuerman.name, spuerman.age)}	//传入双参
	override def toString = s"$name is $age superman"
}
object spuerman{var name = "zieox" ; var age  = 22}
scala> new spuerman					--->res4: spuerman = zieox is 22 superman
scala> new spuerman(name="sss")				--->res5: spuerman = sss is 22 superman
scala> new spuerman("sss",23)				--->res6: spuerman = sss is 23 superman
scala> new spuerman(23)					--->res7: spuerman = zieox is 23 superman
//more details:		https://blog.csdn.net/weixin_41074929/article/details/81667613


def this(crustType: String) {
	this(Pizza.DEFAULT_CRUST_SIZE)
	this.crustType = Pizza.DEFAULT_CRUST_TYPE
}
class Pizza () {
	var crustSize = 0
	var crustType = ""
	def this(crustSize: Int) {this() ; this.crustSize = crustSize}
	def this(crustType: String) {this() ; this.crustType = crustType}
	override def toString = s"A $crustSize inch pizza with a $crustType crust"
}

// initial case class
case class Person (var name: String, var age: Int)
val p = Person("John Smith", 30)
val p = Person("John Smith", 30)
val p = Person.apply("John Smith", 30)

// the case class
case class Person (var name: String, var age: Int)
// the companion object
object Person {def apply() = new Person("<no name>", 0) ; def apply(name: String) = new Person(name, 0)}
object CaseClassTest extends App {
	val a = Person()
// corresponds to apply()
	val b = Person("Pam")
// corresponds to apply(name: String)
	val c = Person("William Shatner", 82)
	println(a)
	println(b)
	println(c)
// verify the setter methods work
	a.name = "Leonard Nimoy"
	a.age = 82
	println(a)
}

//4.4. Defining a Private Primary Constructor (私有类)
// this won't compile
class Brain private {override def toString = "This is the brain."}
object Brain {val brain = new Brain ; def getInstance = brain}
object SingletonTest extends App {val brain = Brain.getInstance ; println(brain)}

//
object FileUtils {
	def readFile(filename: String) = {}
	def writeToFile(filename: String, contents: String) {}
}
val contents = FileUtils.readFile("input.txt")
FileUtils.writeToFile("output.txt", content)
val utils = new FileUtils

//4.5. Providing Default Values for Constructor Parameters (为参数设置默认值)
class Socket (val timeout: Int = 10000)
scala> val s = new Socket				--->s: Socket = Socket@7862af46
scala> s.timeout					--->res0: Int = 10000
scala> val s = new Socket(5000)				--->s: Socket = Socket@6df5205c
scala> s.timeout					--->res1: Int = 5000
scala> val s = new Socket(timeout=5000)			--->s: Socket = Socket@52aaf3d2
scala> s.timeout					--->res0: Int = 5000

class Socket(val timeout: Int) {def this() = this(10000);override def toString = s"timeout: $timeout"}
scala> println(new Socket)				--->timeout: 1000, linger: 2000
scala> println(new Socket(3000))			--->timeout: 3000, linger: 2000
scala> println(new Socket(3000, 4000))			--->timeout: 3000, linger: 4000

println(new Socket(timeout=3000, linger=4000))
println(new Socket(linger=4000, timeout=3000))
println(new Socket(timeout=3000))
println(new Socket(linger=4000))

//4.6. Overriding Default Accessors and Mutators (重写scala访问器和转换器)
class Person(private var name: String) {
// this line essentially creates a circular reference
	def name = name
	def name_=(aName: String) { name = aName }
}
---> error

class Person(private var _name: String) {
	def name = _name				// accessor
	def name_=(aName: String) { _name = aName }	// mutator
}
scala> p.name="joohn"					--->p.name: String = joohn
scala> p.name						--->res23: String = joohn

# class Stock (var symbol: String) 的缺省完整版
#在scala中,每一个非私 (not private) 有的var成员都隐式地定义了对应的getter和setter方法

// intentionally left the 'private' modifier off _symbol
class Stock (var _symbol: String) {
	def symbol = _symbol		// getter
	def symbol_= (s: String) {	// setter
		this.symbol = s
		println(s"symbol was updated, new value is $symbol")
	}
}


public class Stock extends java.lang.Object{
	public java.lang.String _symbol();
	public void _symbol_$eq(java.lang.String);
	public java.lang.String symbol();
	public void symbol_$eq(java.lang.String);
	public Stock(java.lang.String);
}

public class Stock extends java.lang.Object{
	public java.lang.String symbol();
	public void symbol_$eq(java.lang.String);
	public Stock(java.lang.String);
}


//4.7.Preventing Getter and Setter Methods from Being Generated
class Stock {
	var delayedPrice: Double = _			// getter and setter methods are generated // _ 表示初始缺省值
	private var currentPrice: Double = _		// keep this field hidden from other classes
}
// Compiled from "Stock.scala"
public class Stock extends java.lang.Object implements scala.ScalaObject{
	public double delayedPrice();
	public void delayedPrice_$eq(double);
	public Stock();
}


class Stock {
// a private field can be seen by any Stock instance
	private var price: Double = _
	def setPrice(p: Double) { price = p }
	def isHigher(that: Stock): Boolean = this.price > that.price
}
object Driver extends App {
	val s1 = new Stock
	s1.setPrice(20)
	val s2 = new Stock
	s2.setPrice(100)
	println(s2.isHigher(s1))
}

class Stock {
// a private[this] var is object-private, and can only be seen
// by the current instance
	private[this] var price: Double = _
	def setPrice(p: Double) { price = p }
// error: this method won't compile because price is now object-private
	def isHigher(that: Stock): Boolean = this.price > that.price
}


//4.8. Assigning a Field to a Block or Function
class Foo {
// set 'text' equal to the result of the block of code
	val text = {
		var lines = ""
		try {lines = io.Source.fromFile("/home/lufax/桌面/ts.py").getLines.mkString} 
		catch {case e: Exception => lines = "Error happened"}
		lines
	}
	println(text)
	}
object Test extends App {val f = new Foo}

//
class Foo {
	import scala.xml.XML
// assign the xml field to the result of the load method
	val xml = XML.load("http://example.com/foo.xml")
}

===> simplification Foo
class Foo {val text =io.Source.fromFile("/etc/passwd").getLines.foreach(println)}
// or 
class Foo {lazy val text = io.Source.fromFile("/etc/passwd").getLines.foreach(println)}
object Test extends App {val f = new Foo}

//4.9. Setting Uninitialized var Field Types	(设置未初始化的var字段类型)
case class Person(var username: String, var password: String) {
	var age = 0
	var firstName = ""
	var lastName = ""
	var address = None: Option[Address]
}
case class Address(city: String, state: String, zip: String)	
scala> val a = new Person("zieox","1121")				--->a: Person = Person(zieox,1121)
scala> a.age=22								--->a.age: Int = 22

val p = Person("alvinalexander", "secret")
p.address = Some(Address("Talkeetna", "AK", "99676"))
p.address.foreach { a =>println(a.city) ; println(a.state) ; println(a.zip)}

//4.10. Handling Constructor Parameters When Extending a Class	(扩展类时处理构造函数参数)
class Person (var name: String, var address: Address) {override def toString = if (address == null) name else s"$name @ $address"}
class Employee (name: String, address: Address, var age: Int) extends Person (name, address) {// rest of the class}
# 	extends the Person by using "THE Parameters"(使用父类的参数字段)
case class Address (city: String, state: String)
val teresa = new Employee("Teresa", Address("Louisville", "KY"), 25)
scala> teresa.name				--->res0: String = Teresa
scala> teresa.address				--->res1: Address = Address(Louisville,KY)
scala> teresa.age				--->res2: Int = 25

//4.11. Calling a Superclass Constructor (调用superclass)
class Animal (var name: String, var age: Int) {
	def this (name: String) {this(name, 0)}
	override def toString = s"$name is $age years old"
}
// calls the Animal one-arg constructor
class Dog (name: String) extends Animal (name) {println("Dog constructor called")}
// call the two-arg constructor
class Dog (name: String) extends Animal (name, 0) {println("Dog constructor called")}

//
case class Address (city: String, state: String)
case class Role (role: String)
class Person (var name: String, var address: Address) {
// no way for Employee auxiliary constructors to call this constructor
	def this (name: String) {this(name, null) ; address = null}
	override def toString = if (address == null) name else s"$name @ $address"
}
class Employee (name: String, role: Role, address: Address) extends Person (name, address) {
	def this (name: String) {this(name, null, null)}
	def this (name: String, role: Role) {this(name, role, null)}
	def this (name: String, address: Address) {this(name, null, address)}
}

	class A{
	    public A(String name){
             }
	}


//4.12. When to Use an Abstract Class (使用抽象类)
trait Animal(name: String)				// this won't compile
abstract class Animal(name: String)			// it will be compiled

//创建一个BaseController
abstract class BaseController(db: Database) {
	def save { db.save }
	def update { db.update }
	def delete { db.delete }
	// abstract
	def connect
	// an abstract method that returns a String
	def getStatus: String
	// an abstract method that takes a parameter
	def setServerName(serverName: String)
}


//4.13. Defining Properties in an Abstract Base Class (or Trait) (在抽象基类中定义属性或特质)
abstract class Pet (name: String) {
	val greeting: String
	var age: Int
	def sayHello { println(greeting) }
	override def toString = s"I say $greeting, and I'm $age"
}

class Dog (name: String) extends Pet (name) {val greeting = "Woof" ; var age = 2}
class Cat (name: String) extends Pet (name) {val greeting = "Meow" ; var age = 5}

object AbstractFieldsDemo extends App {
	val dog = new Dog("Fido")
	val cat = new Cat("Morris")
	dog.sayHello
	cat.sayHello
	println(dog)
	println(cat)
	// verify that the age can be changed
	cat.age = 10
	println(cat)
}

import scala.*;
import scala.runtime.BoxesRunTime;
public abstract class Pet{
	public abstract String greeting();
	public abstract int age();
	public abstract void age_$eq(int i);
	public void sayHello() {Predef$.MODULE$.println(greeting());}
	public String toString(){}
	public Pet(String name){}
}
//
abstract class Pet (name: String) {def greeting: String}
class Dog (name: String) extends Pet (name) {val greeting = "Woof"}
object Test extends App {val dog = new Dog("Fido") ; println(dog.greeting)}

//Concrete val fields in abstract classes (抽象类中的val字段)
abstract class Animal {
	val greeting = "Hello"
	def sayHello { println(greeting) }
	def run
}
// provide an initial value
class Dog extends Animal {
	override val greeting = "Woof"
// override the value
	def run { println("Dog is running") }
}

abstract class Animal {val greeting = { println("Animal"); "Hello" }}
class Dog extends Animal {override val greeting = { println("Dog"); "Woof" }}
object Test extends App {new Dog}

//final不能被override
abstract class Animal {final val greeting = "Hello"}		 // made the field 'final'
class Dog extends Animal {val greeting = "Woof"}		// this line won't compile


//Concrete var fields in abstract classes (抽象类中的var字段)
abstract class Animal {
	var greeting = "Hello"
	var age = 0
	override def toString = s"I say $greeting, and I'm $age years old."
}
class Dog extends Animal {greeting = "Woof" ; age = 2}
//如果Animal类private的 也可以直接赋值
private String greeting;
private int age;
public Animal(){greeting = "Hello"; age = 0;}

class Dog extends Animal {
	def <init>(): Dog = {
		Dog.super.<init>();
		Dog.this.greeting_=("Woof");
		Dog.this.age_=(2);
		()
	}
}


//Don’t use null
trait Animal {
	val greeting: Option[String]
	var age: Option[Int] = None
	override def toString = s"I say $greeting, and I'm $age years old."
}
class Dog extends Animal {val greeting = Some("Woof") ; age = Some(2)}
object Test extends App {val d = new Dog ; println(d)}
--->			I say Some(Woof), and I'm Some(2) years old.


//4.14. Generating Boilerplate Code with Case Classes (用case类生成样板代码)
case class Person(name: String, relation: String)
val emily = Person("Emily", "niece")
//使用var字段
case class Company (var name: String)
scala> val c = Company("Mat-Su Valley Programming")			--->c: Company = Company(Mat-Su Valley Programming)
scala> c.name								--->res112: String = Mat-Su Valley Programming
scala> c.name= "Valley Programming"					--->c.name: String = Valley Programming
scala> emily match { case Person(n, r) => println(n, r) }		--->(Emily,niece)

//case 中的 copy方法
case class Employee(name: String, loc: String, role: String)
scala> val fred = Employee("Fred", "Anchorage", "Salesman")		--->fred: Employee = Employee(Fred,Anchorage,Salesman)
scala> val joe = fred.copy(name="Joe", role="Mechanic")			--->joe: Employee = Employee(Joe,Anchorage,Mechanic)


//4.15. Defining an equals Method (Object Equality)  (定义相等性)
//by Instance & hashCode
class Person (name: String, age: Int) {
	def canEqual(a: Any) = a.isInstanceOf[Person]	//判断类型相等 instance详解:https://itang.iteye.com/blog/1128707
	override def equals(that: Any): Boolean =
		that match {
			case that: Person => that.canEqual(this) && this.hashCode == that.hashCode
			case _ => false
		}
	override def hashCode:Int = {
		val prime = 31
		var result = 1
		result = prime * result + age;
		result = prime * result + (if (name == null) 0 else name.hashCode)
		return result
	}
}
//
import org.scalatest.FunSuite
class PersonTests extends FunSuite {
// these first two instances should be equal
	val nimoy = new Person("Leonard Nimoy", 82)
	val nimoy2 = new Person("Leonard Nimoy", 82)
	val shatner = new Person("William Shatner", 82)
	val ed = new Person("Ed Chigliak", 20)
// all tests pass
	test("nimoy == nimoy") { assert(nimoy == nimoy) }
	test("nimoy == nimoy2") { assert(nimoy == nimoy2) }
	test("nimoy2 == nimoy") { assert(nimoy2 == nimoy) }
	test("nimoy != shatner") { assert(nimoy != shatner) }
	test("shatner != nimoy") { assert(shatner != nimoy) }
	test("nimoy != null") { assert(nimoy != null) }
	test("nimoy != String") { assert(nimoy != "Leonard Nimoy") }
	test("nimoy != ed") { assert(nimoy != ed) }
}

// canEqual & equals WITH Employee
class Employee(name: String, age: Int, var role: String)extends Person(name, age){
	override def canEqual(a: Any) = a.isInstanceOf[Employee]
	override def equals(that: Any): Boolean = that match {
		case that: Employee => that.canEqual(this) && this.hashCode == that.hashCode
		case _ => false
	}
	override def hashCode:Int = {
		val ourHash = if (role == null) 0 else role.hashCode
		super.hashCode + ourHash
	}
}

//4.16. Creating Inner Classes (创建内部类)
//ex:
class PandorasBox {
	case class Thing (name: String)
	var things = new collection.mutable.ArrayBuffer[Thing]()
	things += Thing("Evil Thing #1")
	things += Thing("Evil Thing #2")
	def addThing(name: String) { things += new Thing(name) }
}
object ClassInAClassExample extends App {val p = new PandorasBox ; p.things.foreach(println)}
scala>  val p = new PandorasBox				--->p: PandorasBox = PandorasBox@22a6d75c
scala> p.addThing("Evil Thing #4")
scala> p.addThing("Evil Thing #3")
scala> p						--->res4: PandorasBox = PandorasBox@22a6d75c
scala>  p.things.foreach(println)
	--->		Thing(Evil Thing #1)
			Thing(Evil Thing #2)
			Thing(Evil Thing #4)
			Thing(Evil Thing #3)

“Opposed to Java-like languages where such inner classes are members of the enclosing class, 
in Scala, such inner classes are bound to the outer object.” The following code demonstrates this:

object ClassInObject extends App {
// inner classes are bound to the object
	val oc1 = new OuterClass
	val oc2 = new OuterClass
	val ic1 = new oc1.InnerClass
	val ic2 = new oc2.InnerClass
	ic1.x = 10
	ic2.x = 20
	println(s"ic1.x = ${ic1.x}")
	println(s"ic2.x = ${ic2.x}")
}
class OuterClass {class InnerClass {var x = 1}}
//InnerClassDemo2
object InnerClassDemo2 extends App {
// class inside object
	println(new OuterObject.InnerClass().x)
// object inside class
	println(new OuterClass().InnerObject.y)
}
object OuterObject {class InnerClass {var x = 1}}
class OuterClass {object InnerObject {val y = 2}}



========================================================CP5 Methods (方法)
//5.1. Controlling Method Scope (控制方法范围)
//Object-private scope (私有对象)
class Foo {
	private[this] def isFoo = true
	def doFoo(other: Foo) {if (other.isFoo) {println("hello")} }// this line won't compile
}
--->		//value isFoo is not a member of Foo
class Animal {private def heartBeat {}}
class Dog extends Animal {heartBeat} // won't compile

//Protected scope  (Protected对象) 与subclass共享
class Animal {protected def breathe {}}
class Dog extends Animal {breathe}

//在scala中 即使时同一包下,也不能直接访问 某一class的protected对象
package world {
	class Animal {protected def breathe {}}
	class Jungle {val a = new Animal ; a.breathe}
}
--->		// error: this line won't compile

//Package scope (包对象范围)
package com.acme.coolapp.model {
	class Foo {
		private[model] def doX {}
		private def doY {}
	}
	class Bar {
		val f = new Foo
		f.doX // compiles		这里Foo的doX对model私有
		f.doY // won't compile		这里Foo的doY对model的Foo私有
	}
}

//More package-level control 
package com.acme.coolapp.model {
	class Foo {
		private[model] def doX {}
		private[coolapp] def doY {}
		private[acme] def doZ {}
	}
}
import com.acme.coolapp.model._
package com.acme.coolapp.view {
	class Bar {
		val f = new Foo
		f.doX // won't compile
		f.doY
		f.doZ
	}
}
package com.acme.common {
	class Bar {
		val f = new Foo
		f.doX // won't compile
		f.doY // won't compile
		f.doZ
	}
}

//Public scope (public字段)
package com.acme.coolapp.model {class Foo {def doX {}}}
package org.xyz.bar {class Bar {val f = new com.acme.coolapp.model.Foo ; f.doX}}

//Table 5-1. Descriptions of Scala’s access control modifiers
Access modifier			Description
private[this] 			The method is available only to the current instance of the class it’s declared in.
private 			The method is available to the current instance and other instances of the class it’s declared in.
protected 			The method is available only to instances of the current class and subclasses of the current class.
private[model] 			The method is available to all classes beneath the com.acme.coolapp.model package.
private[coolapp] 		The method is available to all classes beneath the com.acme.coolapp package.
private[acme] 			The method is available to all classes beneath the com.acme package.
(no modifier) 			The method is public.

//5.2. Calling a Method on a Superclass (调用超类方法)
class WelcomeActivity extends Activity {override def onCreate(bundle: Bundle) {super.onCreate(bundle) /*more code here ...*/}}
class FourLeggedAnimal {
	def walk { println("I'm walking") }
	def run { println("I'm running") }
}
class Dog extends FourLeggedAnimal {def walkThenRun {super.walk ; super.run}}
scala> d.walk					--->I'm walking
scala> d.run					--->I'm running
scala> d.walkThenRun
--->		I'm walking
		I'm running

//Controlling which trait you call a method from  (调用不同特质中的方法)
trait Human {def hello = "the Human trait"}
trait Mother extends Human {override def hello = "Mother"}
trait Father extends Human {override def hello = "Father"}

class Child extends Human with Mother with Father {
	def printSuper = super.hello
	def printMother = super[Mother].hello
	def printFather = super[Father].hello
	def printHuman = super[Human].hello
}

object Test extends App {
	val c = new Child
	println(s"c.printSuper = ${c.printSuper}")
	println(s"c.printMother = ${c.printMother}")
	println(s"c.printFather = ${c.printFather}")
	println(s"c.printHuman = ${c.printHuman}")
}

trait Animal {def walk { println("Animal is walking") }}
class FourLeggedAnimal extends Animal {override def walk { println("I'm walking on all fours") }}
class Dog extends FourLeggedAnimal {
	def walkThenRun {
		super.walk				// works
		super[FourLeggedAnimal].walk 		// works
		//super[Animal].walk			// error: won't compile
	}
}

class Dog extends FourLeggedAnimal with Animal {
	def walkThenRun {
		super.walk				// works
		super[FourLeggedAnimal].walk 		// works
		super[Animal].walk			// compile
	}
}


//5.3. Setting Default Values for Method Parameters (设置方法参数的默认值)
class Connection {
	def makeConnection(timeout: Int = 5000, protocol: String= "http") {
		println("timeout = %d, protocol = %s".format(timeout, protocol)) // more code here
	}
}
c.makeConnection()
c.makeConnection(2000)
c.makeConnection(3000, "https")
scala> val c = new Connection				--->c: Connection = Connection@385db088
scala> c.makeConnection()				--->timeout = 5000, protocol = http
scala> c.makeConnection(2000)				--->timeout = 2000, protocol = http
scala> c.makeConnection(3000, "https")			--->timeout = 3000, protocol = https
c.makeConnection(timeout=10000)
c.makeConnection(protocol="https")
c.makeConnection(timeout=10000, protocol="https")


class Connection {
// corrected implementation
	def makeConnection(timeout: Int, protocol: String = "http") {
		println("timeout = %d, protocol = %s".format(timeout, protocol))
// more code here
	}
}
scala> c.makeConnection(1000)			--->timeout = 1000, protocol = http
scala> c.makeConnection(1000, "https")		--->timeout = 1000, protocol = https

//5.4. Using Parameter Names When Calling a Method  (调用方法时使用参数名)
class Pizza {
	var crustSize = 12
	var crustType = "Thin"
	def update(crustSize: Int, crustType: String) {
		this.crustSize = crustSize
		this.crustType = crustType
	}
override def toString = {"A %d inch %s crust pizza.".format(crustSize, crustType)}
}
val p = new Pizza
p.update(crustSize = 16, crustType = "Thick")
p.update(crustType = "Pan", crustSize = 14)

//5.5. Defining a Method That Returns Multiple Items (Tuples) (定义返回多个项的方法)
scala> val a= (1,"st",'s')			--->a: (Int, String, Char) = (1,st,s)
scala> val (q,b,c)=a
--->				q: Int = 1
				b: String = st
				c: Char = s
//by java
public class StockInfo {
	String symbol;
	double currentPrice;
	double bidPrice;
	public StockInfo(String symbol, double currentPrice, double bidPrice) {
		this.symbol = symbol;
		this.currentPrice = currentPrice;
		this.bidPrice = bidPrice;
	}
}
return new StockInfo("NFLX", 100.00, 101.00);

//Working with tuples
def getStockInfo = ("NFLX", 100.00)
val (symbol, currentPrice) = getStockInfo
scala> val result = getStockInfo			--->x: (java.lang.String, Double, Double) = (NFLX,100.0)
scala> result._1					--->res0: java.lang.String = NFLX
scala> result._2					--->res1: Double = 100.0


//5.6. Forcing Callers to Leave Parentheses off Accessor Methods
class Pizza {def crustSize = 12}
scala> val p = new Pizza				--->p: Pizza = Pizza@3a3e8692
scala> p.crustSize()					---><console>:10: error
scala> p.crustSize					--->res0: Int = 12

//5.7. Creating Methods That Take Variable-Argument Fields (可变参数方法)
def printAll(strings: String*) {strings.foreach(println)}
printAll()
printAll("foo")
printAll("foo", "bar")
printAll("foo", "bar", "baz")

val fruits = List("apple", "banana", "cherry")
printAll(fruits: _*)

def printAll(numbers: Int*) {println(numbers.getClass)}
scala> printAll(1, 2, 3)				--->class scala.collection.mutable.WrappedArray$ofInt
scala> printAll()					--->class scala.collection.immutable.Nil$

//printAll不同的写法
// version 1
def printAll(numbers: Int*) {numbers.foreach(println)}
// version 2
def printAll(numbers: Int*) {for (i <- numbers) println}

//5.8. Declaring That a Method Can Throw an Exception  (声明异常方法)
@throws(classOf[Exception])
override def play {// exception throwing code here ...}
@throws(classOf[IOException])
@throws(classOf[LineUnavailableException])
@throws(classOf[UnsupportedAudioFileException])
def playSoundFileWithJavaAudio {}// exception throwing code here ...

object BoomTest extends App {
	def boom { throw new Exception }
	println("Before boom")
	boom
// this line is never reached
	println("After boom")
}


//5.9. Supporting a Fluent Style of Programming (支持流畅的编程风格)
person.setFirstName("Leonard").setLastName("Nimoy").setAge(82).setCity("Los Angeles").setState("California")
//set_person
class Person {
	protected var fname = ""
	protected var lname = ""
	def setFirstName(firstName: String): this.type = {fname = firstName ; this}
	def setLastName(lastName: String): this.type = {lname = lastName ; this}
}
class Employee extends Person {
	protected var role = ""
	def setRole(role: String): this.type = {this.role = role ; this}
	override def toString = {"%s, %s, %s".format(fname, lname, role)}
}
object Main extends App {
	val employee = new Employee			// use the fluent methods
	employee.setFirstName("Al").setLastName("Alexander").setRole("Developer")
	println(employee)
}

final class Pizza {
	import scala.collection.mutable.ArrayBuffer
	private val toppings = ArrayBuffer[String]()
	private var crustSize = 0
	private var crustType = ""
	def addTopping(topping: String) = {toppings += topping ; this}
	def setCrustSize(crustSize: Int) = {this.crustSize = crustSize ; this}
	def setCrustType(crustType: String) = {this.crustType = crustType ; this}
	def print() {
		println(s"crust size: $crustSize")
		println(s"crust type: $crustType")
		println(s"toppings: $toppings")
	}
}

object FluentPizzaTest extends App {
	val p = new Pizza
	p.setCrustSize(14).setCrustType("thin").addTopping("cheese").addTopping("green olives").print()
}


========================================================CP6 Objects (伴生对象)
type Throwable = java.lang.Throwable
type Exception = java.lang.Exception
type Error = java.lang.Error
type Seq[+A] = scala.collection.Seq[A]
val Seq = scala.collection.Seq

//6.1. Object Casting
// open/read the application context file
val ctx = new ClassPathXmlApplicationContext("applicationContext.xml")
// instantiate our dog and cat objects from the application context
val dog = ctx.getBean("dog").asInstanceOf[Animal]
val cat = ctx.getBean("cat").asInstanceOf[Animal]
val yaml = new Yaml(new Constructor(classOf[EmailAccount]))
val emailAccount = yaml.load(text).asInstanceOf[EmailAccount]

//asInstanceOf  isInstanceOf
https://blog.csdn.net/lcg910978041/article/details/53157618
scala> val a = 10					--->a: Int = 10
scala> val b = a.asInstanceOf[Long]			--->b: Long = 10
scala> val c = a.asInstanceOf[Byte]			--->c: Byte = 10


//6.2. The Scala Equivalent of Java’s .class (Java类的Scala等价物)
//使用classof  (InsteadOf)  .class
val info = new DataLine.Info(classOf[TargetDataLine], null)
info = new DataLine.Info(TargetDataLine.class, null);

scala> val stringClass = classOf[String]			--->stringClass: Class[String] = class java.lang.String
scala> stringClass.getMethods

//6.3. Determining the Class of an Object (确定对象的类 by getClass)
def printAll(numbers: Int*) {println("class: " + numbers.getClass)}
scala> printAll(1, 2, 3)					--->class scala.collection.mutable.WrappedArray$ofInt
scala> printAll()						--->class scala.collection.immutable.Nil$

scala> val hello = <p>Hello, <br/>world</p>			--->hello: scala.xml.Elem = <p>Hello, <br/>world</p>
scala> hello.child.foreach(e => println(e.getClass))
--->	class scala.xml.Text
	class scala.xml.Elem
	class scala.xml.Text

scala> def printClass(c: Any) { println(c.getClass) }		--->printClass: (c: Any)Unit
scala> printClass(1)						--->class java.lang.Integer
scala> printClass("yo")						--->class java.lang.String

def printAll(numbers: Int*) {numbers.foreach(println)}

//6.4. Launching an Application with an Object (创建object)
object Hello extends App {println("Hello, world")}
$ scalac Hello.scala
$ scala Hello							--->Hello, world

object Hello extends App {
	if (args.length == 1) println(s"Hello, ${args(0)}")
	else println("I didn't get your name.")
}
lufax@lufax:~$ scala /home/lufax/桌面/tes.scala "zieox.jlus"		--->Hello, zieox.jlus

object Hello2 {def main(args: Array[String]) {println("Hello, world")}}
lufax@lufax:~$ scala /home/lufax/桌面/tes.scala				--->Hello, world


//6.5. Creating Singletons with object (用伴生对象对象创建单例)
object CashRegister {def open { println("opened") } ; def close { println("closed") }}
object Main extends App {CashRegister.open ; CashRegister.close}


import java.util.Calendar
import java.text.SimpleDateFormat
object DateUtils {
	def getCurrentDate: String = getCurrentDateTime("EEEE, MMMM d")	// as "Thursday, November 29"
	def getCurrentTime: String = getCurrentDateTime("K:m aa")	// as "6:20 p.m."
	private def getCurrentDateTime(dateTimeFormat: String): String = {// a common function used by other date/time functions
		val dateFormat = new SimpleDateFormat(dateTimeFormat)
		val cal = Calendar.getInstance()
		dateFormat.format(cal.getTime())
	}
}
scala> DateUtils.getCurrentTime					--->res0: String = 10:13 AM
scala> DateUtils.getCurrentDate					--->res1: String = Friday, July 6


//6.6. Creating Static Members with Companion Objects (使用伴生对象创建静态成员)
// Pizza class
class Pizza (var crustType: String) {override def toString = "Crust type is " + crustType}
// companion object
object Pizza {
	val CRUST_TYPE_THIN = "thin"
	val CRUST_TYPE_THICK = "thick"
	def getFoo = "Foo"
}
scala> println(Pizza.CRUST_TYPE_THIN)				--->thin
scala> println(Pizza.getFoo)					--->Foo
scala> var p = new Pizza(Pizza.CRUST_TYPE_THICK)		--->p: Pizza = Crust type is thick
scala> println(p)						--->Crust type is thick



class Foo {private val secret = 2}
object Foo {def double(foo: Foo) = foo.secret * 2}		// access the private class field 'secret'
object Driver extends App {
	val f = new Foo
	println(Foo.double(f)) // prints 4
}
class Foo {def printObj { println(s"I can see ${Foo.obj}") }}	// access the private object field 'obj'
object Foo {private val obj = "Foo's object"}
object Driver extends App {
	val f = new Foo
	f.printObj
}

//6.7. Putting Common Code in Package Objects  (将公共代码放入包对象中)
package com.alvinalexander.myapp
package object model {
// field
	val MAGIC_NUM = 42
// method
	def echo(a: Any) { println(a) }
// enumeration
	object Margin extends Enumeration {
		type Margin = Value
		val TOP, BOTTOM, LEFT, RIGHT = Value
	}
// type definition
	type MutableMap[K, V] = scala.collection.mutable.Map[K, V]
	val MutableMap = scala.collection.mutable.Map
}

package com.alvinalexander.myapp.model
object MainDriver extends App {
// access our method, constant, and enumeration
	echo("Hello, world")
	echo(MAGIC_NUM)
	echo(Margin.LEFT)
// use our MutableMap type (scala.collection.mutable.Map)
	val mm = MutableMap("name" -> "Al")
	mm += ("password" -> "123")
	for ((k,v) <- mm) printf("key: %s, value: %s\n", k, v)
}

//6.8. Creating Object Instances Without Using the new	Keyword (不使用new关键字创建对象实例 )
//Creating a companion object with an apply method (使用apply方法)
class Person {var name: String = _}
object Person {
	def apply(name: String): Person = {
		var p = new Person
		p.name = name
		p
	}
}
val dawn = Person("Dawn")
val a = Array(Person("Dan"), Person("Elijah"))

//Declare your class as a case class (声明样例类)
case class Person (var name: String)
val p = Person("Fred Flinstone")
val p = Person("Fred Flinstone")
	---into this code:
val p = Person.apply("Fred Flinstone")

//Providing multiple constructors with additional apply methods (为多个构造函数提供附加的应用方法)
class Person {
	var name = ""
	var age = 0
}
object Person {
	// a one-arg constructor
	def apply(name: String): Person = {
		var p = new Person
		p.name = name
		p
	}
	// a two-arg constructor
	def apply(name: String, age: Int): Person = {
		var p = new Person
		p.name = name
		p.age = age
		p
	}
}


case class Person (var name: String, var age: Int)
// define two auxiliary constructors
object Person {
	def apply() = new Person("<no name>", 0)
	def apply(name: String) = new Person(name, 0)
}

object Test extends App {
	val a = Person()
	val b = Person("Al")
	val c = Person("William Shatner", 82)
	println(a)
	println(b)
	println(c)
// test the mutator methods
	a.name = "Leonard Nimoy"
	a.age = 82
	println(a)
}

//6.9. Implement the Factory Method in Scala with apply  (用apply在scala中实现工厂方法)
trait Animal {def speak}
object Animal {
	private class Dog extends Animal {override def speak { println("woof") }}
	private class Cat extends Animal {override def speak { println("meow") }}
	// the factory method
	def apply(s: String): Animal = {if (s == "dog") new Dog else new Cat}
}

scala> val cat = Animal("cat")				--->cat: Animal = Animal$Cat@486f8860
scala> cat.speak					--->meow
scala> val dog = Animal("dog")				--->dog: Animal = Animal$Dog@412798c1
scala> dog.speak					--->woof

// an alternative factory method (use one or the other)
def getAnimal(s: String): Animal = {if (s == "dog") return new Dog else return new Cat}
val cat = Animal.getAnimal("cat") // returns a Cat
val dog = Animal.getAnimal("dog") // returns a Dog


========================================================CP7 Packaging and Imports
//7.1. Packaging with the Curly Braces Style Notation (用大括号样式符号包装)
package com.acme.store {class Foo { override def toString = "I am com.acme.store.Foo" }}

package orderentry {class Foo { override def toString = "I am orderentry.Foo" }}
// one package nested inside the other
package customers {
	class Foo { override def toString = "I am customers.Foo" }
	// this Foo is different than customers.Foo or orderentry.Foo
	package database {class Foo { override def toString = "I am customers.database.Foo" }}
}
// a simple object to test the packages and classes
object PackageTests extends App {
	println(new orderentry.Foo)
	println(new customers.Foo)
	println(new customers.database.Foo)
}

//7.2. Importing One or More Members (import 成员)
import java.io.File
import java.io.IOException
import java.io.FileNotFoundException
import java.io.{File, IOException, FileNotFoundException}


package foo
import java.io.File
import java.io.PrintWriter
class Foo {import javax.swing.JFrame}
class Bar {import scala.util.Random}
class Bar {def doBar = {import scala.util.Random ; println("")}}

//7.3. Renaming Members on Import (导入后重命名)
import java.util.{ArrayList => JavaList}
val list = new JavaList[String]
import java.util.{Date => JDate, HashMap => JHashMap}
val map = new HashMap[String, String]
import java.util.{HashMap => JavaHashMap}
import scala.collection.mutable.{Map => ScalaMutableMap}
import java.util.{HashMap => JavaHashMap}
import scala.collection.mutable.Map

scala> import System.out.{println => p}				--->import System.out.{println=>p}
scala> p("hello")						--->hello

//7.4. Hiding a Class During the Import Process (在导入过程中隐藏类)
import java.util.{Random => _, _}
scala> val r = new Random					---><console>:10: error

scala> import java.util.{List=>_ ,Map=>_ ,Set => _,_}		--->import java.util.{List=>_, Map=>_, Set=>_, _}
scala> new ArrayList						--->res0: java.util.ArrayList[Nothing] = []

//7.5. Using Static Imports (静态导入)
scala> import java.lang.Math._				--->import java.lang.Math._
scala> val a = sin(0)					--->a: Double = 0.0
scala> val a = cos(PI)					--->a: Double = −1.0

scala> import java.awt.Color._				--->import java.awt.Color._
scala> println(RED)					--->java.awt.Color[r=255,g=0,b=0]
scala> val currentColor = BLUE				--->currentColor: java.awt.Color = java.awt.Color[r=0,g=0,b=255]

package com.alvinalexander.dates;
public enum Day {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY}
import com.alvinalexander.dates.Day._
// somewhere after the import statement
if (date == SUNDAY || date == SATURDAY) println("It's the weekend.")

//7.6. Using Import Statements Anywhere (import anywhere)
package foo
import scala.util.Random
class ImportTests {def printRandom {val r = new Random}}

package foo
class ImportTests {
	import scala.util.Random
	def printRandom {val r = new Random}
}
def getRandomWaitTimeInMinutes: Int = {
	import com.alvinalexander.pandorasbox._
	val p = new Pandora
	p.release
}

def printRandom {
{
	import scala.util.Random
	val r1 = new Random 	// this is fine
}
	val r2 = new Random	// error: not found: type Random
}

package orderentry {
	import foo._
	// more code here ...
}
package customers {
	import bar._
	// more code here ...
	package database {
		import baz._
		// more code here ...
	}
}

package foo
// available to all classes defined below
import java.io.File
import java.io.PrintWriter
class Foo {
	// only available inside this class
	import javax.swing.JFrame

}
class Bar {
	// only available inside this class
	import scala.util.Random
}

========================================================CP8 Traits(特质)
//kind like
class Woodpecker extends Bird with TreeScaling with Pecking

//8.1. Using a Trait as an Interface(使用特征作为接口)
trait BaseSoundPlayer {
	def play
	def close
	def pause
	def stop
	def resume
}

trait Dog {
	def speak(whatToSay: String)
	def wagTail(enabled: Boolean)
}
//use
class Foo extends Trait1 with Trait2 with Trait3 with Trait4 { ...}

//If a class extends a trait but does not implement the abstract methods defined in that trait, it must be declared abstract:
//一个类继承特质必须申明其签名的方法体,不然要用abstract class
class Mp3SoundPlayer extends BaseSoundPlayer {
	def play{ // code here ... }
	def close { // code here ... }
	def pause { // code here ... }
	def stop{ // code here ... }
	def resume { // code here ... }
}

abstract class SimpleSoundPlayer extends BaseSoundPlayer {
	def play { ... }
	def close { ... }
}
//In other uses, one trait can extend another trait:(特质继承特质)
trait Mp3BaseSoundFilePlayer extends BaseSoundFilePlayer {
	def getBasicPlayer: BasicPlayer
	def getBasicController: BasicController
	def setGain(volume: Double)
}

abstract class Animal {def speak}
trait WaggingTail {
	def startTail { println("tail started") }
	def stopTail { println("tail stopped") }
}
trait FourLeggedAnimal {
	def walk
	def run
}
class Dog extends Animal with WaggingTail with FourLeggedAnimal {
	// implementation code here ...
	def speak { println("Dog says 'woof'") }
	def walk { println("Dog is walking") }
	def run { println("Dog is running") }
}

val f = new Foo with Trait1

//8.2. Using Abstract and Concrete Fields in Traits(抽象和具体领域在特征中的应用)
trait PizzaTrait {
	var numToppings: Int 		// abstract
	var size = 14			// concrete
	val maxNumToppings = 10		// concrete
}

class Pizza extends PizzaTrait {
	var numToppings = 0		// 'override' not needed
	size = 16			// 'var' and 'override' not needed
}

//trait中val的maxNumToppings 需要override
trait PizzaTrait {val maxNumToppings: Int }
class Pizza extends PizzaTrait {override val maxNumToppings = 10}

//8.3. Using a Trait Like an Abstract Class (像抽象类一样使用特质)
trait Pet {
	def speak { println("Yo") }
	def comeToMaster
}
// concrete implementation
// abstract method
class Dog extends Pet {def comeToMaster { ("I'm coming!") }}	// don't need to implement 'speak' if you don't need to
class Cat extends Pet {
// override the speak method
	override def speak { ("meow") }
	def comeToMaster { ("That's not gonna happen.") }
}
//abstract class FlyingPet extends Pet {def fly { ("I'm flying!") }}

//8.4. Using Traits as Simple Mixins (混用trait)
trait Tail {
	def wagTail { println("tail is wagging") }
	def stopTail { println("tail is stopped") }
}
abstract class Pet (var name: String) {
	def speak // abstract
	def ownerIsHome { println("excited") }
	def jumpForJoy { println("jumping for joy") }
}

abstract class Pet (var name: String) {
	def speak // abstract
	def ownerIsHome { println("excited") }
	def jumpForJoy { println("jumping for joy") }
}
class Dog (name: String) extends Pet (name) with Tail {
	def speak { println("woof") }
	override def ownerIsHome {
		wagTail
		speak
	}
}

object Test extends App {val zeus = new Dog("Zeus") ; zeus.ownerIsHome ; zeus.jumpForJoy}

//8.5. Limiting Which Classes Can Use a Trait by Inheritance(通过继承限制哪些类可以使用特性)
trait [TraitName] extends [SuperThing]
class StarfleetComponent
trait StarfleetWarpCore extends StarfleetComponent
class Starship extends StarfleetComponent with StarfleetWarpCore
class StarfleetComponent
trait StarfleetWarpCore extends StarfleetComponent
class RomulanStuff
// won't compile
class Warbird extends RomulanStuff with StarfleetWarpCore

abstract class Employee
class CorporateEmployee extends Employee
class StoreEmployee extends Employee
trait DeliversFood extends StoreEmployee
class DeliveryPerson extends StoreEmployee with DeliversFood
class Receptionist extends CorporateEmployee with DeliversFood


//8.6. Marking Traits So They Can Only Be Used by Subclasses of a Certain Type (标记特性,以便它们只能由某一类型的子类使用)
trait StarfleetWarpCore {this: Starship => println("hello") } // more code here ...
class Starship
class Enterprise extends Starship with StarfleetWarpCore	// it will compiled
//任何与特性混合的具体类必须确保其类型符合特性的自身类型。 
class RomulanShip
class Warbird extends RomulanShip with StarfleetWarpCore	// this won't compile


trait WarpCore {this: Starship with WarpCoreEjector with FireExtinguisher => }
class Starship
trait WarpCoreEjector
trait FireExtinguisher
// this works
class Enterprise extends Starship
with WarpCore
with WarpCoreEjector
with FireExtinguisher

//8.7. Ensuring a Trait Can Only Be Added to a Type That Has a Specific Method(确保特性只能添加到具有特定方法的类型中)
trait WarpCore {this: { def ejectWarpCore(password: String): Boolean } => }
class Starship {/* code here ... */}

class Enterprise extends Starship with WarpCore {
	def ejectWarpCore(password: String): Boolean = {if (password == "password") {println("ejecting core") ; true} else {false}}
}

trait WarpCore {
	this: {
		def ejectWarpCore(password: String): Boolean
		def startWarpCore: Unit
		} =>
}
class Starship
class Enterprise extends Starship with WarpCore {
	def ejectWarpCore(password: String): Boolean = {if (password == "password") { println("core ejected"); true } else false}
	def startWarpCore { println("core started") }
}

//8.8. Adding a Trait to an Object Instance (向对象实例添加trait)
class DavidBanner
trait Angry {println("You won't like me ...")}
object Test extends App {val hulk = new DavidBanner with Angry}

trait Debugger {def log(message: String) {/* do something with message*/}}
val child = new Child					// no debugger
val problemChild = new ProblemChild with Debugger	// debugger added as the object is created

//8.9. Extending a Java Interface Like a Trait (像特性一样扩展Java接口)
public interface Animal {public void speak();}
public interface Wagging {public void wag();}
public interface Running {public void run();}

class Dog extends Animal with Wagging with Running {
	def speak { println("Woof") }
	def wag { println("Tail is wagging!") }
	def run { println("I'm running!") }
}


========================================================CP9 Functional Programming (函数式编程)
val x = List.range(1, 10)
val result = try {aString.toInt} catch {case _ => 0}

//9.1. Using Function Literals (Anonymous Functions)  (使用函数文本(匿名函数))
val evens = List.range(1, 10).filter((i: Int) => i % 2 == 0)
val evens = x.filter(_ % 2 == 0)	//使用匿名函数
//foreach println 匿名写法
x.foreach((i:Int) => println(i))
x.foreach((i) => println(i))
x.foreach(i => println(i))
x.foreach(println(_))
x.foreach(println)

//9.2. Using Functions as Variables (将函数用作变量)
val double = (i: Int) => { i * 2 }
scala> double(2)					--->res5: Int = 4
scala> List(1,2,3).map(double)				--->res6: List[Int] = List(2, 4, 6)

val f = (i: Int) => { i % 2 == 0 }
val f:(Int) => Boolean = i =>{ i % 2 == 0}
val f:Int => Boolean = i => { i % 2 == 0}
val f:Int => Boolean = i => i % 2 == 0
val f:Int => Boolean = _ % 2 == 0

val add = (x: Int, y: Int) => { x + y }
val add = (x: Int, y: Int) => x + y
// explicit approach
val add: (Int, Int) => Int = (x,y) => { x + y }
val add: (Int, Int) => Int = (x,y) => x + y

val addThenDouble:(Int,Int) => Int = (x,y) => {val a = x + y ; 2 * a}
//Using a method like an anonymous functions
def modMethod(i:Int) = i % 2 == 0
def modMethod(i:Int) = {i % 2 == 0}
def modMethod(i:Int):Boolean = i % 2 == 0
def modMethod(i:Int):Boolean = {i % 2 == 0}
val list = List.range(1, 10)
list.filter(modMethod)
//Assigning an existing function/method to a function variable

scala> val c = scala.math.cos _			--->c: Double => Double = <function1>
scala> val c = scala.math.cos(_)		--->c: Double => Double = <function1>
scala> c(0)					--->res9: Double = 1.0

scala> val p = scala.math.pow(_, _)		--->pow: (Double, Double) => Double = <function2>
scala> p(scala.math.E, 2)			--->res0: Double = 7.3890560989306495

//9.3. Defining a Method That Accepts a Simple Function Parameter (定义接受简单函数参数的方法)
def executeFunction(callback:() => Unit) {callback()}
val sayHello = () => { println("Hello") }
scala> executeFunction(sayHello)		--->hello

scala> def plusOne(i: Int): Unit = i + 1	--->plusOne: (i: Int)Unit
scala> plusOne(2)
scala> def plusOne(i: Int) = i + 1		--->plusOne: (i: Int)Int
scala> plusOne(2)				--->res12: Int = 3

//9.4. More Complex Functions
def exec(callback: Int => Unit) {callback(1)}
val plusOne = (i: Int) => { println(i+1) }
exec(plusOne)

executeFunction(f:(String) => Int)
executeFunction(f:String => Int)
executeFunction(f:(Int,Int) => Boolean)

def executeXTimes(callback:() => Unit, numTimes: Int) {for (i <- 1 to numTimes) callback()}
scala> executeXTimes(sayHello, 3)
--->		Hello
		Hello
		Hello

def executeAndPrint(f:(Int, Int) => Int, x: Int, y: Int) {
	val result = f(x, y)
	println(result)
}
val sum = (x: Int, y: Int) => x + y
val multiply = (x: Int, y: Int) => x * y

// 1 - define the method
def exec(callback: (Any, Any) => Unit, x: Any, y: Any) {callback(x, y)}
// 2 - define a function to pass in
val printTwoThings = (a: Any, b: Any) => {println(a);println(b)}
// 3 - pass the function and some parameters to the method
case class Person(name: String)
exec(printTwoThings, "Hello", Person("Dave"))
// 2a - define a method to pass in
def printTwoThings (a: Any, b: Any) {println(a);println(b)}
// 3a - pass the printTwoThings method to the exec method
case class Person(name: String)
exec(printTwoThings, "Hello", Person("Dave"))

//9.5. Using Closures (使用闭包)
package otherscope {
// a method that takes a function and a string, and passes the string into
// the function, and then executes the function
	class Foo {def exec(f:(String) => Unit, name: String) {f(name)}}
}
object ClosureExample extends App {
	var hello = "Hello"
	def sayHello(name: String) { println(s"$hello, $name") }
// execute sayHello from the exec method foo
	val foo = new otherscope.Foo
	foo.exec(sayHello,"Al")
// change the local variable 'hello', then execute sayHello from
// the exec method of foo, and see what happens
	hello = "Hola"
	foo.exec(sayHello,"Lorenzo")
}

//A second example
val isOfVotingAge = (age: Int) => age >= 18
isOfVotingAge(16) 		// false
isOfVotingAge(20)		// true
var votingAge = 18
val isOfVotingAge = (age: Int) => age >= votingAge
isOfVotingAge(16) 		// false
isOfVotingAge(20) 		// true
var votingAge = 18
val isOfVotingAge = (age: Int) => age >= votingAge
isOfVotingAge(16) 		// false
isOfVotingAge(20) 		// true

def printResult(f: Int => Boolean, x: Int) {println(f(x))}
printResult(isOfVotingAge, 20) 	// true
// change votingAge in one scope
votingAge = 21
// the change to votingAge affects the result
printResult(isOfVotingAge, 20) 	// now false

//Using closures with other data types (使用闭包)
import scala.collection.mutable.ArrayBuffer
val fruits = ArrayBuffer("apple")
// the function addToBasket has a reference to fruits
val addToBasket = (s: String) => {
	fruits += s
	println(fruits.mkString(", "))
}
def buyStuff(f: String => Unit, s: String) {f(s)}

scala> buyStuff(addToBasket, "cherries")		--->cherries
scala> buyStuff(addToBasket, "grapes")			--->cherries, grapes

//A comparison to Java
public class SimulatedClosure {
	public static void main (String[] args) {
		Greeter greeter = new Greeter();
		greeter.setHelloPhrase("Hello");
		greeter.sayHello("Al");			// "Hello, Al"
		greeter.setHelloPhrase("Hola");
		greeter.sayHello("Lorenzo"); 		// "Hola, Lorenzo"
		greeter.setHelloPhrase("Yo");
		Bar bar = new Bar(greeter);		// pass the greeter instance to a new Bar
		bar.sayHello("Adrian");			// invoke greeter.sayHello via Bar
	}
}
class Greeter {
	private String helloPhrase;
	public void setHelloPhrase(String helloPhrase) {this.helloPhrase = helloPhrase;}
	public void sayHello(String name) {System.out.println(helloPhrase + ", " + name);}
}

class Bar {
	private Greeter greeter;
	public Bar (Greeter greeter) {this.greeter = greeter;}
	public void sayHello(String name) {greeter.sayHello(name);}
}


//9.6. Using Partially Applied Functions (使用部分应用的函数)
val sum = (a:Int,b:Int,c:Int) => a + b + c
val f = sum(1, 2, _: Int)			based on Func:sum (base_value about 1,2)
def wrap(prefix: String, html: String, suffix: String) = {prefix + html + suffix}
val wrapWithDiv = wrap("<div>", _: String, "</div>")
scala> wrapWithDiv("<p>Hello, world</p>")			--->res0: String = <div><p>Hello, world</p></div>
scala> wrapWithDiv("<img src=\"/images/foo.png\" />")		--->res1: String = <div><img src="/images/foo.png" /></div>

//9.7. Creating a Function That Returns a Function
def saySomething(prefix: String) = (s: String) => {prefix + " " + s}


def greeting(language: String) = (name: String) => {
	language match {
		case "english" => "Hello, " + name
		case "spanish" => "Buenos dias, " + name
	}
}
scala> greeting("english")("jack")				--->res16: String = Hello, jack
scala> greeting("spanish")("jack")				--->res17: String = Buenos dias, jack

def greeting(language: String) = (name: String) => {
	val english = () => "Hello, " + name
	val spanish = () => "Buenos dias, " + name
	language match {
		case "english" => println("returning 'english' function")
		english()
		case "spanish" => println("returning 'spanish' function")
		spanish()
	}
}


scala> val hello = greeting("english")				--->hello: String => java.lang.String = <function1>
scala> val buenosDias = greeting("spanish")			--->buenosDias: String => java.lang.String = <function1>
scala> hello("Al")
--->		returning "english" function
		res0: java.lang.String = Hello, Al
scala> buenosDias("Lorenzo")
--->		returning "spanish" function
		res1: java.lang.String = Buenos dias, Lorenzo

//9.8. Creating Partial Functions (创建部分函数)
val divide = new PartialFunction[Int, Int] {def apply(x: Int) = 42 / x ; def isDefinedAt(x: Int) = x != 0}
scala> divide.isDefinedAt(1)					--->res0: Boolean = true
scala> if (divide.isDefinedAt(1)) divide(1)			--->res1: AnyVal = 42
scala> divide.isDefinedAt(0)					--->res2: Boolean = false

//创建divide2
val divide2: PartialFunction[Int,Int] = {case d: Int if d != 0 => 42 / d}

//The PartialFunction explained (部分函数解释)
trait PartialFunction[-A,+B] extends (A) => B

PartialFunction[Int, String]
// converts 1 to "one", etc., up to 5
val convertLowNumToString = new PartialFunction[Int, String] {
	val nums = Array("one", "two", "three", "four", "five")
	def apply(i: Int) = nums(i-1)
	def isDefinedAt(i: Int) = i > 0 && i < 6
}

//orElse and andThen
// converts 1 to "one", etc., up to 5
val convert1to5 = new PartialFunction[Int, String] {
	val nums = Array("one", "two", "three", "four", "five")
	def apply(i: Int) = nums(i-1)
	def isDefinedAt(i: Int) = i > 0 && i < 6
}
// converts 6 to "six", etc., up to 10
val convert6to10 = new PartialFunction[Int, String] {
	val nums = Array("six", "seven", "eight", "nine", "ten")
	def apply(i: Int) = nums(i-6)
	def isDefinedAt(i: Int) = i > 5 && i < 11
}

scala> val handle1to10 = convert1to5 orElse convert6to10		--->handle1to10: PartialFunction[Int,String] = <function1>
scala> handle1to10(3)							--->res0: String = three
scala> handle1to10(8)							--->res1: String = eight

val divide: PartialFunction[Int, Int] = {case d: Int if d != 0 => 42 / d}
scala> List(0,1,2) map { divide }					--->scala.MatchError: 0
scala> List(0,1,2) collect { divide }					--->res0: List[Int] = List(42, 21)
scala> List(42, "cat") collect { case i: Int => i + 1 }			--->res0: List[Int] = List(43)

val sample = 1 to 5
val isEven: PartialFunction[Int, String] = {case x if x % 2 == 0 => x + " is even"}
val evenNumbers = sample collect isEven
val isOdd: PartialFunction[Int, String] = {case x if x % 2 == 1 => x + " is odd"}
val numbers = sample map (isEven orElse isOdd)

//9.9. A Real-World Example
object NewtonsMethod {
	def main(args: Array[String]) {driver}
	def driver {// the f(x) and f'(x) functions
		val fx = (x: Double) => 3*x + math.sin(x) - math.pow(math.E, x)
		val fxPrime = (x: Double) => 3 + math.cos(x) - math.pow(Math.E, x)
		val initialGuess = 0.0
		val tolerance = 0.00005
			// pass f(x) and f'(x) to the Newton's Method function, along with
			// the initial guess and tolerance
		val answer = newtonsMethod(fx, fxPrime, initialGuess, tolerance)
		println(answer)
}

def newtonsMethod(fx: Double => Double,fxPrime: Double => Double,x: Double,tolerance: Double): Double = {
	var x1 = x
	var xNext = newtonsMethodHelper(fx, fxPrime, x1)
	while (math.abs(xNext - x1) > tolerance) {
		x1 = xNext
		println(xNext) // debugging (intermediate values)
		xNext = newtonsMethodHelper(fx, fxPrime, x1)
	}
	xNext
}


========================================================CHAPTER 10 Collections
//10.1. Understanding the Collections Hierarchy (了解集合层次结构)
val v = Vector(1, 2, 3)
v.sum				// 6
v.filter(_ > 1)			// Vector(2, 3)
v.map(_ * 2)			// Vector(2, 4, 6)

//Sequences
scala> val x = IndexedSeq(1,2,3)				--->x: IndexedSeq[Int] = Vector(1, 2, 3)
scala> val seq = scala.collection.immutable.LinearSeq(1,2,3)	--->seq: scala.collection.immutable.LinearSeq[Int] = List(1, 2, 3)
//Maps
scala> val m = Map(1 -> "a", 2 -> "b")
			--->m: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> a, 2 -> b)
//因为可变(mutable)的数组不是默认的,所以需要导入
scala> val m = collection.mutable.Map(1 -> "a", 2 -> "b")
			--->m: scala.collection.mutable.Map[Int,String] = Map(2 -> b, 1 -> a)
//Sets
scala> val set = Set(1, 2, 3)					--->set: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> val s = collection.mutable.Set(1, 2, 3)			--->s: scala.collection.mutable.Set[Int] = Set(1, 2, 3)

//10.2. Choosing a Collection Class
//Choosing a sequence

//10.3. Choosing a Collection Method to Solve a Problem
//Methods organized by category
//Filtering methods
collect , diff , distinct ,drop , dropWhile , filter , filterNot ,
find , foldLeft , foldRight , head , headOption , init , intersect ,
last , lastOption , reduceLeft , reduceRight ,remove , slice , tail , take , takeWhile , and union

//Transformer methods
+ , ++ , − , −− , diff , distinct , collect , flatMap , map , reverse , sortWith , takeWhile , zip , and zipWithIndex .

//Grouping methods
groupBy , partition , sliding , span , splitAt , and unzip

//Informational and mathematical methods
canEqual , contains , containsSlice , count , endsWith , exists , find , forAll , has - DefiniteSize ,
indexOf , indexOfSlice , indexWhere , isDefinedAt , isEmpty ,lastIndexOf , lastIndexOfSlice , lastIndexWhere ,
max , min , nonEmpty , product ,segmentLength , size , startsWith , sum . The methods foldLeft , foldRight ,
reduceLeft , and reduceRight

//Others
par , view , flatten , foreach , and mkString
//Common collection methods

//10.4. Understanding the Performance of Collections (了解集合的性能)
var v = Vector[Int]()
for (i <- 1 to 50000) v = v :+ i

//10.5. Declaring a Type When Creating a Collection (创建集合时声明类型)
scala> val x = List(1, 2.0, 33D, 400L)			--->x: List[Double] = List(1.0, 2.0, 33.0, 400.0)
scala> val x = List[Number](1, 2.0, 33D, 400L)		--->x: List[java.lang.Number] = List(1, 2.0, 33.0, 400)
scala> val x = List[AnyVal](1, 2.0, 33D, 400L)		--->x: List[AnyVal] = List(1, 2.0, 33.0, 400)

trait Animal
trait FurryAnimal extends Animal
case class Dog(name: String) extends Animal
case class Cat(name: String) extends Animal
scala> val x = Array(Dog("Fido"), Cat("Felix"))		
				--->x: Array[Product with Serializable with Animal] = Array(Dog(Fido), Cat(Felix))
scala> val x = Array[Animal](Dog("Fido"), Cat("Felix"))
				--->x: Array[Animal] = Array(Dog(Fido), Cat(Felix))
class AnimalKingdom {def animals = Array(Dog("Fido"), Cat("Felix"))}

//10.6. Understanding Mutable Variables with Immutable Collections(用不可变集合理解可变变量 )
scala> var sisters = Vector("Melinda")			--->sisters: collection.immutable.Vector[String] = Vector(Melinda)
scala> sisters = sisters :+ "Melissa"			--->sisters: collection.immutable.Vector[String] = Vector(Melinda, Melissa)
scala> sisters = sisters :+ "Marisa"			--->sisters: collection.immutable.Vector[String] = Vector(Melinda, Melissa, Marisa)
scala> sisters.foreach(println)
--->		Melinda
		Melissa
		Marisa

//10.7. Make Vector Your “Go To” Immutable Sequence(使向量成为“转到”不可变序列)
scala> val v = Vector("a", "b", "c")			--->v: scala.collection.immutable.Vector[java.lang.String] = Vector(a, b, c)
scala> v(0)						--->res0: java.lang.String = a
scala> val a = Vector(1, 2, 3)				--->a: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)
scala> val b = a ++ Vector(4, 5)			--->b: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4, 5)
scala> val c = b.updated(0, "x")			--->c: scala.collection.immutable.Vector[java.lang.String] = Vector(x, b, c)
scala> val a = Vector(1, 2, 3, 4, 5)			--->a: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4, 5)
scala> val b = a.take(2)				--->b: scala.collection.immutable.Vector[Int] = Vector(1, 2)
scala> val c = a.filter(_ > 2)				--->c: scala.collection.immutable.Vector[Int] = Vector(3, 4, 5)
scala> var a = Vector(1, 2, 3)				--->a: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)
scala> a = a ++ Vector(4, 5)				--->a: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4, 5)

//10.8. Make ArrayBuffer Your “Go To” Mutable Sequence(使ArrayBuffer“转到”不可变序列)
import scala.collection.mutable.ArrayBuffer
var fruits = ArrayBuffer[String]()
var ints = ArrayBuffer[Int]()
var nums = ArrayBuffer(1, 2, 3)

// add one element
scala> nums += 4			--->res0: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)
// add two or more elements (method has a varargs parameter)
scala> nums += (5, 6)			--->res1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)
// add elements from another collection
scala> nums ++= List(7, 8)		---->res2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8)
// remove one element
scala> nums -= 9			--->res3: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8)
// remove two or more elements
scala> nums -= (7, 8)			--->res4: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)
// remove elements specified by another sequence
scala> nums --= Array(5, 6)		--->res5: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)

//ArrayBuffer操作方法
val a = ArrayBuffer(1, 2, 3) 			// ArrayBuffer(1,2,3)
a.append(4)					// ArrayBuffer(1,2,3,4)
a.append(5, 6)					// ArrayBuffer(1,2,3,4,5,6)
a.appendAll(Seq(7,8))				// ArrayBuffer(1,2,3,4,5,6,7,8)
a.clear						// ArrayBuffer()
val a = ArrayBuffer(9, 10)			// ArrayBuffer(9, 10)
a.insert(0, 8)					// ArrayBuffer(8,9,10)
a.insert(0, 6, 7)				// ArrayBuffer(6,7,8,9,10)
a.insertAll(0, Vector(4, 5))			// ArrayBuffer(4,5,6,7,8,9,10)
a.prepend(3)					// ArrayBuffer(3,4,5,6,7,8,9,10)
a.prepend(1, 2)					// ArrayBuffer(1,2,3,4,5,6,7,8,9,10)
a.prependAll(Array(0))				// ArrayBuffer(0,1,2,3,4,5,6,7,8,9,10)
val a = ArrayBuffer.range('a', 'h') 		// ArrayBuffer(a, b, c, d, e, f, g)
a.remove(0)					// ArrayBuffer(b, c, d, e, f, g)
a.remove(2, 3)					// ArrayBuffer(b, c, g)
val a = ArrayBuffer.range('a', 'h') 		// ArrayBuffer(a, b, c, d, e, f, g)
a.trimStart(2)					// ArrayBuffer(c, d, e, f, g)
a.trimEnd(2)					// ArrayBuffer(c, d, e)

//10.9. Looping over a Collection with foreach(用foreach循环访问集合)
scala> val x = Vector(1, 2, 3)				--->x: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)
scala> x.foreach((i: Int) => println(i))
--->	1
	2
	3
args.foreach(i => println(i))
args.foreach(println(_))
args.foreach(println)
def printIt(c: Char) { println(c) }
"HAL".foreach(c => printIt(c))
"HAL".foreach(printIt)
"HAL".foreach((c: Char) => println(c))

val longWords = new StringBuilder
"Hello world it's Al".split(" ").foreach{ e =>if (e.length > 4) longWords.append(s" $e") else println("Not added: " + e)}
-->		Not added: it's
		Not added: Al

scala> val m = Map("fname" -> "Tyler", "lname" -> "LeDude")
		--->m: scala.collection.immutable.Map[String,String] = Map(fname -> Tyler, lname -> LeDude)
scala> m foreach (x => println(s"${x._1} -> ${x._2}"))		//在这里foreach遍历的是整键值对
		--->fname -> Tyler
		    lname -> LeDude
movieRatings.foreach {case(movie, rating) => println(s"key: $movie, value: $rating")}

//10.10. Looping over a Collection with a for Loop (使用for循环在集合上循环 )
scala> val fruits = Traversable("apple", "banana", "orange")		--->fruits: Traversable[String] = List(apple, banana, orange)
scala> for (f <- fruits) println(f)					--->apple;banana;orange
scala> val fruits = Array("apple", "banana", "orange")			--->fruits: Array[String] = Array(apple, banana, orange)
for (i <- 0 until fruits.size) println(s"element $i is ${fruits(i)}")
scala> for ((elem, count) <- fruits.zipWithIndex) {println(s"element $count is $elem")}		//use zipWithIndex

for ((elem,count) <- fruits.zip(Stream from 1)) {println(s"element $count is $elem")}
		--->element 1 is apple
		    element 2 is banana
		    element 3 is orange
scala> val fruits=Array("apple", "banana", "orange")			--->fruits: Array[java.lang.String] = Array(apple, banana, orange)
scala> val newArray=for (e<-fruits) yield e.toUpperCase		--->newArray: Array[java.lang.String] = Array(APPLE, BANANA, ORANGE)

scala> val newArray = for (fruit <- fruits) yield {val upper = fruit.toUpperCase;upper}	// imagine this required multiple lines
def upperReverse(s: String) = {s.toUpperCase.reverse}					// imagine this is a long algorithm

scala> val names = Map("fname" -> "Ed", "lname" -> "Chigliak")
		--->names: scala.collection.immutable.Map[String,String] = Map(fname -> Ed, lname -> Chigliak)
scala> for ((k,v) <- names) println(s"key: $k, value: $v")
		--->key: fname, value: Ed
		    key: lname, value: Chigliak
val filehere=(new java.io.File("/home/lufax/桌面")).listFiles
scala> for (i<-filehere) if (i.getName.endsWith(".py")) println(i) 

//10.11. Using zipWithIndex or zip to Create Loop Counters (使用zipwithindex或zip创建循环计数器)
val days = Array("Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday")
days.zipWithIndex.foreach {case(day, count) => println(s"$count is $day")}
for ((day, count) <- days.zipWithIndex) {println(s"$count is $day")}
days.zipWithIndex.foreach { d =>println(s"${d._2} is ${d._1}")}
val fruits = Array("apple", "banana", "orange")
for (i <- 0 until fruits.size) println(s"element $i is ${fruits(i)}")

//10.12. Using Iterators (使用迭代器)
scala> val it = Iterator(1,2,3)				--->it: Iterator[Int] = non-empty iterator
scala> it.foreach(println)				--->1;2;3
scala> it.foreach(println)				--->(no output here)
scala> it.to[Tab]

//10.13. Transforming One Collection to Another with for/yield (用for/yield将一个集合转换为另一个集合)
scala> val a = Array(1, 2, 3, 4, 5)			--->a: Array[Int] = Array(1, 2, 3, 4, 5)
scala> for (e <- a) yield e				--->res0: Array[Int] = Array(1, 2, 3, 4, 5)
scala> for (e <- a) yield e * 2				--->res1: Array[Int] = Array(2, 4, 6, 8, 10)
scala> for (e <- a) yield e % 2				--->res2: Array[Int] = Array(1, 0, 1, 0, 1)
scala> val fruits = Vector("apple", "banana", "lime", "orange")
			--->fruits: Vector[String] = Vector(apple, banana, lime, orange)
scala> val ucFruits = for (e <- fruits) yield e.toUpperCase
		--->ucFruits: Vector[String] = Vector(APPLE, BANANA, LIME, ORANGE)
scala> for (i <- 0 until fruits.length) yield (i, fruits(i))
		--->res0: scala.collection.immutable.IndexedSeq[(Int, String)] = Vector((0,apple), (1,banana), (2,lime), (3,orange))
scala> for (f <- fruits) yield (f, f.length)
		--->res1: Vector[(String, Int)] = Vector((apple,5), (banana,6), (lime,4), (orange,6))

case class Person (name: String)
val friends = Vector("Mark", "Regina", "Matt")

scala> for (f <- friends) yield Person(f)		--->res0: Vector[Person] = Vector(Person(Mark), Person(Regina), Person(Matt))
scala> val x = for (e <- fruits if e.length < 6) yield e.toUpperCase		--->x: List[java.lang.String] = List(APPLE, LIME)

scala> val fruits = scala.collection.mutable.ArrayBuffer("apple", "banana")
		--->fruits: scala.collection.mutable.ArrayBuffer[java.lang.String] = ArrayBuffer(apple, banana)
scala> val x = for (e <- fruits) yield e.toUpperCase
		--->x: scala.collection.mutable.ArrayBuffer[java.lang.String] = ArrayBuffer(APPLE, BANANA)
scala> val fruits = "apple" :: "banana" :: "orange" :: Nil
		--->fruits: List[java.lang.String] = List(apple, banana, orange)
scala> val x = for (e <- fruits) yield e.toUpperCase
		--->x: List[java.lang.String] = List(APPLE, BANANA, ORANGE)

for {file <- files ; if hasSoundFileExtension(file) ; if !soundFileIsLong(file)} yield file
scala> val cars = Vector("Mercedes", "Porsche", "Tesla")			--->cars: Vector[String] = Vector(Mercedes, Porsche, Tesla)
scala> for {c <- cars;if c.startsWith("M") } yield c				--->res0: Vector[String] = Vector(Mercedes)

//10.14. Transforming One Collection to Another with map(使用map将一个集合转换为另一个集合)
scala> val helpers = Vector("adam", "kim", "melissa")
		--->helpers: scala.collection.immutable.Vector[java.lang.String] = Vector(adam, kim, melissa)
// the long form
scala> val caps = helpers.map(e => e.capitalize)	//首字母大写
		--->caps: scala.collection.immutable.Vector[String] = Vector(Adam, Kim, Melissa)

scala> val caps = helpers.map(_.capitalize)		--->caps: scala.collection.immutable.Vector[String] = Vector(Adam, Kim, Melissa)
scala> val names = Array("Fred", "Joe", "Jonathan")	--->names: Array[java.lang.String] = Array(Fred, Joe, Jonathan)
scala> val lengths = names.map(_.length)		--->lengths: Array[Int] = Array(4, 3, 8)
scala> val nieces = List("Aleka", "Christina", "Molly")			--->nieces: List[String] = List(Aleka, Christina, Molly)
scala> val elems = nieces.map(niece => <li>{niece}</li>)
		--->elems: List[scala.xml.Elem] = List(<li>Aleka</li>, <li>Christina</li>, <li>Molly</li>)
scala> val ul = <ul>{nieces.map(i => <li>{i}</li>)}</ul>
		--->ul: scala.xml.Elem = <ul><li>Aleka</li><li>Christina</li><li>Molly</li></ul>

scala> def plusOne(c: Char): Char = (c.toByte+1).toChar			--->plusOne: (c: Char)Char
scala> "HAL".map(plusOne)						--->res0: String = IBM
scala> " eggs, milk, butter, Coco Puffs ".split(",").map(_.trim)	--->res68: Array[String] = Array(eggs, milk, butter, Coco Puffs)

scala> val people = List("adam", "kim", "melissa")			--->people: List[java.lang.String] = List(adam, kim, melissa)
// map
scala> val caps1 = people.map(_.capitalize)				--->caps1: List[String] = List(Adam, Kim, Melissa)
// for/yield
scala> val caps2 = for (f <- people) yield f.capitalize			--->caps2: List[String] = List(Adam, Kim, Melissa)

scala> val fruits = List("apple", "banana", "lime", "orange", "raspberry")
		--->fruits: List[java.lang.String] = List(apple, banana, lime, orange, raspberry)
scala> val newFruits = fruits.map( f =>if (f.length < 6) f.toUpperCase )
scala> newFruits.filter(_ != ())					--->res0: List[Any] = List(APPLE, LIME)
scala> val fruits = List("apple", "banana", "lime", "orange", "raspberry")
		--->fruits: List[String] = List(apple, banana, lime, orange, raspberry)
scala> fruits.filter(_.length < 6).map(_.toUpperCase)
		--->res1: List[String] = List(APPLE, LIME)

//10.15. Flattening a List of Lists with flatten(扁平化列表)
scala> val lol = List(List(1,2), List(3,4))			--->lol: List[List[Int]] = List(List(1, 2), List(3, 4))
scala> val result = lol.flatten					--->result: List[Int] = List(1, 2, 3, 4)
scala> val a = Array(Array(1,2), Array(3,4))			--->a: Array[Array[Int]] = Array(Array(1, 2), Array(3, 4))
scala> a.flatten						--->res0: Array[Int] = Array(1, 2, 3, 4)
scala> val couples = List(List("kim", "al"), List("julia", "terry"))
			--->couples: List[List[String]] = List(List(kim, al), List(julia, terry))
scala> val people = couples.flatten
			--->people: List[String] = List(kim, al, julia, terry)
scala> val people = couples.flatten.map(_.capitalize).sorted
			--->people: List[String] = List(Al, Julia, Kim, Terry)
val myFriends = List("Adam", "David", "Frank")
val adamsFriends = List("Nick K", "Bill M")
val davidsFriends = List("Becca G", "Kenny D", "Bill M")
val friendsOfFriends = List(adamsFriends, davidsFriends)
scala> val uniqueFriendsOfFriends = friendsOfFriends.flatten.distinct
			--->uniqueFriendsOfFriends: List[String] = List(Nick K, Bill M, Becca G, Kenny D)
scala> val list = List("Hello", "world")			--->list: List[java.lang.String] = List(Hello, world)
scala> list.flatten						--->res0: List[Char] = List(H, e, l, l, o, w, o, r, l, d)
scala> val x = Vector(Some(1), None, Some(3), None)		--->x: Vector[Option[Int]] = Vector(Some(1), None, Some(3), None)
scala> x.flatten						--->res1: Vector[Int] = Vector(1, 3)

//10.16. Combining map and flatten with flatMap (map 与 flatten结合)
val bag = List("1", "2", "three", "4", "one hundred seventy five")
def toInt(in: String): Option[Int] = {try {Some(Integer.parseInt(in.trim))} catch {case e: Exception => None}}
scala> bag.flatMap(toInt).sum					--->res0: Int = 7
scala> bag.map(toInt)					--->res0: List[Option[Int]] = List(Some(1), Some(2), None, Some(4), None)
scala> bag.map(toInt).flatten				--->res1: List[Int] = List(1, 2, 4)
scala> bag.map(toInt).flatten.sum			--->res2: Int = 7
scala> bag.flatMap(toInt).filter(_ > 1)			--->res4: List[Int] = List(2, 4)
scala> bag.flatMap(toInt).takeWhile(_ < 4)		--->res5: List[Int] = List(1, 2)
scala> bag.flatMap(toInt).partition(_ > 3)		--->res6: (List[Int], List[Int]) = (List(4),List(1, 2))

//10.17. Using filter to Filter a Collection(使用filter)
scala> val x = List.range(1, 10)			--->x: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
// create a list of all the even numbers in the list
scala> val evens = x.filter(_ % 2 == 0)			--->evens: List[Int] = List(2, 4, 6, 8)

scala> val fruits = Set("orange", "peach", "apple", "banana")
			--->fruits: scala.collection.immutable.Set[java.lang.String] = Set(orange, peach, apple, banana)
scala> val x = fruits.filter(_.startsWith("a"))			--->x: scala.collection.immutable.Set[String] = Set(apple)
scala> val y = fruits.filter(_.length > 5)			--->y: scala.collection.immutable.Set[String] = Set(orange, banana)
scala> val list = "apple" :: "banana" :: 1 :: 2 :: Nil		--->list: List[Any] = List(apple, banana, 1, 2)
scala> val strings = list.filter {case s: String => true ; case _ => false}		//使用filter case
def onlyStrings(a: Any) = a match {case s: String => true ; case _ => false}
val strings = list.filter(onlyStrings)
def getFileContentsWithoutBlanksComments(canonicalFilename: String):
List[String] = {io.Source.fromFile(canonicalFilename).getLines.toList.filter(_.trim != "").filter(_.charAt(0) != '#')}

//10.18. Extracting a Sequence of Elements from a Collection (从集合中提取元素序列)
scala> val x = (1 to 10).toArray				--->x: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> val y = x.drop(3)					--->y: Array[Int] = Array(4, 5, 6, 7, 8, 9, 10)
scala> val y = x.dropWhile(_ < 6)				--->y: List[Int] = List(6, 7, 8, 9, 10)
scala> val y = x.dropRight(4)					--->y: Array[Int] = Array(1, 2, 3, 4, 5, 6)
//take extracts the first N elements from the sequence:
scala> val y = x.take(3)					--->y: Array[Int] = Array(1, 2, 3)
//takeWhile returns elements as long as the predicate you supply returns true :
scala> val y = x.takeWhile(_ < 5)				--->y: Array[Int] = Array(1, 2, 3, 4)
scala> val y = x.takeRight(3)					--->y: Array[Int] = Array(8, 9, 10)
scala> val peeps = List("John", "Mary", "Jane", "Fred")		--->peeps: List[String] = List(John, Mary, Jane, Fred)
//slice 方法
scala> peeps.slice(1,3)						--->res0: List[String] = List(Mary, Jane)

scala> val nums = (1 to 5).toArray				--->nums: Array[Int] = Array(1, 2, 3, 4, 5)
nums.head				// 1
nums.headOption				// Some(1)
nums.init				// Array(1, 2, 3, 4)
nums.last				// 5
nums.lastOption				// Some(5)
nums.tail				// Array(2, 3, 4, 5)

//10.19. Splitting Sequences into Subsets (groupBy,partition, etc.) (分割序列by groupBy/partition)
scala> val x = List(15, 10, 5, 8, 20, 12)			--->x: List[Int] = List(15, 10, 5, 8, 20, 12)
scala> val y = x.groupBy(_ > 10)
		--->y: Map[Boolean,List[Int]] = Map(false -> List(10, 5, 8), true -> List(15, 20, 12))
scala> val y = x.partition(_ > 10)				--->y: (List[Int], List[Int]) = (List(15, 20, 12), List(10, 5, 8))
scala> val y = x.span(_ < 20)					--->y: (List[Int], List[Int]) = (List(15, 10, 5, 8), List(20, 12))
scala> val y = x.splitAt(2)					--->y: (List[Int], List[Int]) = (List(15, 10), List(5, 8, 20, 12))

scala> val (a,b) = x.partition(_ > 10)
		--->a: List[Int] = List(15, 20, 12)
		    b: List[Int] = List(10, 5, 8)
scala> val groups = x.groupBy(_ > 10)
		--->groups: scala.collection.immutable.Map[Boolean,List[Int]] = Map(false -> List(10, 5, 8), true -> List(15, 20, 12))
scala> val trues = groups(true)					--->trues: List[Int] = List(15, 20, 12)
scala> val falses = groups(false)				--->falses: List[Int] = List(10, 5, 8)

scala> val nums = (1 to 5).toArray				--->nums: Array[Int] = Array(1, 2, 3, 4, 5)
//with aliding size = 2
scala> nums.sliding(2).toList
		--->res0: List[Array[Int]] = List(Array(1, 2), Array(2, 3), Array(3, 4), Array(4, 5))
// size = 2, step = 2
scala> nums.sliding(2,2).toList					--->res1: List[Array[Int]] = List(Array(1, 2), Array(3, 4), Array(5))
// size = 2, step = 3
scala> nums.sliding(2,3).toList					--->res2: List[Array[Int]] = List(Array(1, 2), Array(4, 5))

scala> val listOfTuple2s = List((1,2), ('a', 'b'))		--->listOfTuple2s: List[(AnyVal, AnyVal)] = List((1,2), (a,b))
scala> val x = listOfTuple2s.unzip				--->x: (List[AnyVal], List[AnyVal]) = (List(1, a),List(2, b))
//use unzip
scala> val couples = List(("Kim", "Al"), ("Julia", "Terry"))	--->couples: List[(String, String)] = List((Kim,Al), (Julia,Terry))
scala> val (women, men) = couples.unzip
		--->women: List[String] = List(Kim, Julia)
		    men: List[String] = List(Al, Terry)

scala> val women = List("Kim", "Julia")				--->women: List[String] = List(Kim, Julia)
scala> val men = List("Al", "Terry")				--->men: List[String] = List(Al, Terry)
scala> val couples = women zip men				--->couples: List[(String, String)] = List((Kim,Al), (Julia,Terry))

//10.20. Walking Through a Collection with the reduce and fold Methods(通过reduce和fold方法浏览一个集合)
scala> val a = Array(12, 6, 15, 2, 20, 9)			--->a: Array[Int] = Array(12, 6, 15, 2, 20, 9)
scala> a.reduceLeft(_ + _)					--->res0: Int = 64
scala> a.reduceLeft(_ * _)					--->res1: Int = 388800
scala> a.reduceLeft(_ min _)					--->res2: Int = 2
scala> a.reduceLeft(_ max _)					--->res3: Int = 20

//Show each step in the process
val findMax = (x: Int, y: Int) => {
	val winner = x max y
	println(s"compared $x to $y, $winner was larger")
	winner
}

scala> a.reduceLeft(findMax)
--->				compared 12 to 6, 12 was larger
				compared 12 to 15, 15 was larger
				compared 15 to 2, 15 was larger
				compared 15 to 20, 20 was larger
				compared 20 to 9, 20 was larger
				res3: Int = 20

//The code that reduceLeft uses under the hood looks like this:
// you provide the sequence 'seq' and the function 'f'
var result = seq(0)
for (i <- 1 until seq.length) {val next = seq(i) ; result = f(result, next)}

//Working with other sequences and types

scala> val peeps = Vector("al", "hannah", "emily", "christina", "aleka")
		--->peeps: scala.collection.immutable.Vector[java.lang.String] = Vector(al, hannah, emily, christina, aleka)
scala> peeps.reduceLeft((x,y) => if (x.length > y.length) x else y)			--->res0: String = christina

//foldLeft, reduceRight, and foldRight
scala> val a = Array(1, 2, 3)				--->a: Array[Int] = Array(1, 2, 3)
scala> a.reduceLeft(_ + _)				--->res0: Int = 6
scala> a.foldLeft(20)(_ + _)				--->res1: Int = 26
scala> a.foldLeft(100)(_ + _)				--->res2: Int = 106

//The difference between reduceLeft and reduceRight
val divide = (x: Double, y: Double) => {
	val result = x / y
	println(s"divided $x by $y to yield $result")
	result
}
val a = Array(1.0, 2.0, 3.0)		//by2  ->
scala> a.reduceLeft(divide)
--->		divided 1.0 by 2.0 to yield 0.5
		divided 0.5 by 3.0 to yield 0.16666666666666666
		res0: Double = 0.16666666666666666
scala> a.reduceRight(divide)
--->		divided 2.0 by 3.0 to yield 0.6666666666666666
		divided 1.0 by 0.6666666666666666 to yield 1.5
		res1: Double = 1.5
//scanLeft and scanRight
val product = (x: Int, y: Int) => {
	val result = x * y
	println(s"multiplied $x by $y to yield $result")
	result
}
scala> val a = Array(1, 2, 3)				--->a: Array[Int] = Array(1, 2, 3)
scala> a.scanLeft(10)(product)
--->				multiplied 10 by 1 to yield 10
				multiplied 10 by 2 to yield 20
				multiplied 20 by 3 to yield 60
				res0: Array[Int] = Array(10, 10, 20, 60)
//As you can see, scanLeft returns a new sequence, rather than a single value.(scanLeft返回一个Array)
val findMax = (x: Int, y: Int) => {
	Thread.sleep(10)
	val winner = x max y
	println(s"compared $x to $y, $winner was larger")
	winner
}
val a = Array.range(0,50)
a.par.reduce(findMax)

//10.21. Extracting Unique Elements from a Sequence (从序列抽取单一元素)
scala> val x = Vector(1, 1, 2, 3, 3, 4)		--->x: scala.collection.immutable.Vector[Int] = Vector(1, 1, 2, 3, 3, 4)
scala> val y = x.distinct			--->y: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4)
scala> val s = x.toSet				--->s: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)

//Using distinct with your own classes
class Person(firstName: String, lastName: String) {
	override def toString = s"$firstName $lastName"
	def canEqual(a: Any) = a.isInstanceOf[Person]
	override def equals(that: Any): Boolean =
		that match {
			case that: Person => that.canEqual(this) && this.hashCode == that.hashCode
			case _ => false
		}
	override def hashCode: Int = {
		val prime = 31
		var result = 1
		result = prime * result + lastName.hashCode;
		result = prime * result + (if (firstName == null) 0 else firstName.hashCode)
		return result
	}
}
object Person {def apply(firstName: String, lastName: String) =new Person(firstName, lastName)}

val dale1 = new Person("Dale", "Cooper")
val dale2 = new Person("Dale", "Cooper")
val ed = new Person("Ed", "Hurley")
val list = List(dale1, dale2, ed)
val uniques = list.distinct

scala> val list = List(dale1, dale2, ed)		--->list: List[Person] = List(Dale Cooper, Dale Cooper, Ed Hurley)
scala> val uniquePeople = list.distinct			--->uniquePeople: List[Person] = List(Dale Cooper, Ed Hurley)


//10.22. Merging Sequential Collections (合并序列集合)
scala> val a =collection.mutable.ArrayBuffer(1,2,3)	--->a: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
scala> a++=Seq(5,6,7)					--->res0: a.type = ArrayBuffer(1, 2, 3, 5, 6, 7)
scala> val a = Array(1,2,3)				--->a: Array[Int] = Array(1, 2, 3)
scala> val b = Array(4,5,6)				--->b: Array[Int] = Array(4, 5, 6)
scala> val c = a ++ b					--->c: Array[Int] = Array(1, 2, 3, 4, 5, 6)

scala> val a = Array(1,2,3,4,5)				--->a: Array[Int] = Array(1, 2, 3, 4, 5)
scala> val b = Array(4,5,6,7,8)				--->b: Array[Int] = Array(4, 5, 6, 7, 8)
//取交集(intersect)
scala> val c = a.intersect(b)				--->c: Array[Int] = Array(4, 5)
//取并集(union)
scala> val c = a.union(b)				--->c: Array[Int] = Array(1, 2, 3, 4, 5, 4, 5, 6, 7, 8)
//取差集(diff) (a diff b 在a不在b)
scala> val c = a diff b					--->c: Array[Int] = Array(1, 2, 3)
scala> val c = b diff a					--->c: Array[Int] = Array(6, 7, 8)
//拼接(concat)
scala> Array.concat(a, b)				--->res0: Array[Int] = Array(1, 2, 3, 4, 4, 5, 6, 7)
//使用 ::: 拼接list
scala> val a = List(1,2,3,4)				--->a: List[Int] = List(1, 2, 3, 4)
scala> val b = List(4,5,6,7)				--->b: List[Int] = List(4, 5, 6, 7)
scala> val c = a ::: b					--->c: List[Int] = List(1, 2, 3, 4, 4, 5, 6, 7)

val a = Array(1,2,3,11,4,12,4,5)
val b = Array(6,7,4,5)
// the elements in a that are not in b(在a不在b)
scala> val c = a.toSet diff b.toSet			--->c: scala.collection.immutable.Set[Int] = Set(1, 2, 12, 3, 11)
// the elements in b that are not in a(在b不在a)
scala> val d = b.toSet diff a.toSet			--->d: scala.collection.immutable.Set[Int] = Set(6, 7)
//
scala> val i = a.intersect(b)				--->i: Array[Int] = Array(4, 5)
scala> val c = a.toSet -- i.toSet			--->c: scala.collection.immutable.Set[Int] = Set(1, 2, 12, 3, 11)
scala> val d = b.toSet -- i.toSet			--->d: scala.collection.immutable.Set[Int] = Set(6, 7)


//10.23. Merging Two Sequential Collections into Pairs with zip (用zip将两个连续集合合并为一对)
scala> val women = List("Wilma", "Betty")		--->women: List[String] = List(Wilma, Betty)
scala> val men = List("Fred", "Barney")			--->men: List[String] = List(Fred, Barney)
scala> val couples = women zip men			--->couples:List[(String,String)]=List((Wilma,Fred),(Betty,Barney))
for ((wife, husband) <- couples) {println(s"$wife is married to $husband")}
scala> val couplesMap = couples.toMap
		--->couplesMap: scala.collection.immutable.Map[String,String] = Map(Wilma -> Fred, Betty -> Barney)

//zip时 当两个序列元素个数不一时
// three elements
scala> val products = Array("breadsticks", "pizza", "soft drink")
// one element
scala> val prices = Array(4)
// one resulting element
scala> val productsWithPrice = products.zip(prices)	--->productsWithPrice: Array[(String, Int)] = Array((breadsticks,4))
scala> val (a,b) = productsWithPrice.unzip
--->		a: collection.mutable.IndexedSeq[String] = ArrayBuffer(breadsticks, pizza, soft drink)
		b: collection.mutable.IndexedSeq[Double] = ArrayBuffer(4.0, 10.0, 1.5)


//10.24. Creating a Lazy View on a Collection (在集合上创建惰性视图)
val view = (1 to 100).view
val x = view.force
val x = (1 to 1000).view.map { e => Thread.sleep(10) ; e * 2 }

scala> val arr = (1 to 10).toArray			--->arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> val view = arr.view.slice(2, 5)			--->view: scala.collection.mutable.IndexedSeqView[Int,Array[Int]] = SeqViewS(...)
scala> view(0) = 10
scala> view(1) = 20
scala> view(2) = 30
scala> arr						--->res0: Array[Int] = Array(1, 2, 10, 20, 30, 6, 7, 8, 9, 10)
val a = Array.range(0,123456789,3)
val a = Array.range(0,123456789).view


//10.25. Populating a Collection with a Range(用范围填充集合 )
scala> Array.range(1, 5)				--->res0: Array[Int] = Array(1, 2, 3, 4)
scala> List.range(0, 10)				--->res1: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> Vector.range(0, 10, 2)				--->res2: collection.immutable.Vector[Int] = Vector(0, 2, 4, 6, 8)

scala> val a = (0 until 10).toArray			--->a: Array[Int] = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> val list = 1 to 10 by 2 toList			--->list: List[Int] = List(1, 3, 5, 7, 9)
scala> val list = (1 to 10).by(2).toList		--->list: List[Int] = List(1, 3, 5, 7, 9)

scala> val set = (0 until 10 by 2).toSet		--->set: scala.collection.immutable.Set[Int] = Set(0, 6, 2, 8, 4)
scala> val letters = ('a' to 'f').toList		--->letters: List[Char] = List(a, b, c, d, e, f)
scala> val letters = ('a' to 'f').by(2).toList		--->letters: List[Char] = List(a, c, e)

scala> val map = (1 to 5).map(e => (e,e))
		--->map: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((1,1), (2,2), (3,3), (4,4), (5,5))
scala> val map = (1 to 5).map(e => (e,e)).toMap
		--->map: scala.collection.immutable.Map[Int,Int] = Map(5 -> 5, 1 -> 1, 2 -> 2, 3 -> 3, 4 -> 4)


//10.26. Creating and Using Enumerations(创建和使用枚举 )
package com.acme.app {
	object Margin extends Enumeration {
		type Margin = Value
		val TOP, BOTTOM, LEFT, RIGHT = Value
	}
}

object Main extends App {
	import com.acme.app.Margin._
	// use an enumeration value in a test
	var currentMargin = TOP
	// later in the code ...
	if (currentMargin == TOP) println("working on Top")
	// print all the enumeration values
	import com.acme.app.Margin
	Margin.values foreach println
}

package com.acme.app {
	trait Margin
	case object TOP extends Margin
	case object RIGHT extends Margin
	case object BOTTOM extends Margin
	case object LEFT extends Margin
}


//10.27. Tuples, for When You Just Need a Bag of Things (当你需要一个bag时,使用Tuples)
scala> val d = ("Debi", 95)				--->d: (String, Int) = (Debi,95)
scala> case class Person(name: String)			--->defined class Person
scala> val t = (3, "Three", new Person("Al"))		--->t: (Int, java.lang.String, Person) = (3,Three,Person(Al))
scala> t._1						--->res1: Int = 3
scala> t._2						--->res2: java.lang.String = Three
scala> t._3						--->res3: Person = Person(Al)

scala> val(x, y, z) = (3, "Three", new Person("Al"))
--->			x: Int = 3
			y: String = Three
			z: Person = Person(Al)

scala> val (x, y, _) = t
--->			x: Int = 3
			y: java.lang.String = Three
scala> val (x, _, _) = t
--->			x: Int = 3
scala> val (x, _, z) = t
--->			x: Int = 3
			z: Person = Person(Al)

scala> val b = "AL" -> "Alabama"			--->b: (java.lang.String, java.lang.String) = (AL,Alabama)
scala> val c = ("AL" -> "Alabama")			--->c: (java.lang.String, java.lang.String) = (AL,Alabama)
scala> c.getClass					--->res18: Class[_ <: (String, String)] = class scala.Tuple2

scala> val x = ("AL" -> "Alabama")			--->x: (java.lang.String, java.lang.String) = (AL,Alabama)
scala> val it = x.productIterator			--->it: Iterator[Any] = non-empty iterator
scala> for (e <- it) println(e)
--->			AL
			Alabama
scala> t.productIterator.toArray			--->res0: Array[Any] = Array(AL, Alabama)


//10.28. Sorting a Collection (对集合排序)
scala> val a = List(10, 5, 8, 1, 7).sorted			--->a: List[Int] = List(1, 5, 7, 8, 10)
scala> val b = List("banana", "pear", "apple", "orange").sorted	--->b: List[String] = List(apple, banana, orange, pear)

scala> List(10, 5, 8, 1, 7).sortWith(_ < _)			--->res1: List[Int] = List(1, 5, 7, 8, 10)
scala> List(10, 5, 8, 1, 7).sortWith(_ > _)			--->res2: List[Int] = List(10, 8, 7, 5, 1)
scala> List("banana", "pear", "apple", "orange").sortWith(_ < _)	--->res3: List[java.lang.String] = List(apple, banana, orange, pear)
scala> List("banana", "pear", "apple", "orange").sortWith(_ > _)	--->res4: List[java.lang.String] = List(pear, orange, banana, apple)

//*map排序 (by values)
val mp = (('A' to 'Z') zip (1 to 26)).toMap
import scala.collection.immutable.ListMap
ListMap(mp.toSeq.sortBy(_._2):_*)

scala> List("banana", "pear", "apple", "orange").sortWith(_.length < _.length)
--->		res5: List[java.lang.String] = List(pear, apple, banana, orange)
scala> List("banana", "pear", "apple", "orange").sortWith(_.length > _.length)
--->		res6: List[java.lang.String] = List(banana, orange, apple, pear)

//使用sortWith排序
def sortByLength(s1: String, s2: String) = {
	println("comparing %s and %s".format(s1, s2))
	s1.length > s2.length
}

scala> List("banana", "pear", "apple").sortWith(sortByLength)
--->		comparing banana and pear
		comparing pear and apple
		comparing apple and pear
		comparing banana and apple
		res0: List[String] = List(banana, apple, pear)


class Person (var name: String) {override def toString = name}
val ty = new Person("Tyler")
val al = new Person("Al")
val paul = new Person("Paul")
val dudes = List(ty, al, paul)
//根据类中参数名排列
scala> val sortedDudes = dudes.sortWith(_.name < _.name)	--->sortedDudes: Array[Person] = Array(Al, Paul, Tyler)
scala> val sortedDudes = dudes.sortWith(_.name > _.name)	--->sortedDudes: Array[Person] = Array(Tyler, Paul, Al)
//Mix in the Ordered trait (混入排序特质)
class Person (var name: String) extends Ordered [Person]{
	override def toString = name
	// return 0 if the same, negative if this < that, positive if this > that
	def compare (that: Person) = {
		if (this.name == that.name) 0
		else if (this.name > that.name)	1
		else	−1
	}
}

def compare (that: Person) = this.name.compare(that.name)
if (al > ty) println("Al") else println("Tyler")


//10.29. Converting a Collection to a String with mkString (使用mkstring将集合转换为字符串)
val a = Array("apple", "banana", "cherry")
scala> a.mkString				--->res1: String = applebananacherry
scala> a.mkString(" ")				--->res2: String = apple banana cherry
scala> a.mkString(", ")				--->res3: String = apple, banana, cherry
scala> a.mkString("[", ", ", "]")		--->res4: String = [apple, banana, cherry]
scala> val a = Array(Array("a", "b"), Array("c", "d"))	--->a: Array[Array[java.lang.String]] = Array(Array(a, b), Array(c, d))
scala> a.flatten.mkString(", ")			--->res5: String = a, b, c, d
scala> val v = Vector("apple", "banana", "cherry")
			--->v: scala.collection.immutable.Vector[String] = Vector(apple, banana, cherry)
scala> v.toString				--->res0: String = Vector(apple, banana, cherry)
















































































+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++hadoop with spark
//RDD(弹性分布式数据集):弹性是指spark可以通过重新安排计算来自动重建丢失分区
//计算最高温度
import org.apache.spark.SparkContext._
import org.apache.spark.{SparkConf, SparkContext}
object MaxTemperature {
	def main(args: Array[String]) {
		val conf = new SparkConf().setAppName("Max Temperature")
		val sc = new SparkContext(conf)
		sc.textFile(args(0))
			.map(_.split("\t"))
			.filter(rec => (rec(1) != "9999" && rec(2).matches("[01459]")))
			.map(rec => (rec(0).toInt, rec(1).toInt))
			.reduceByKey((a, b) => Math.max(a, b))
			.saveAsTextFile(args(1))
	}
}

///RDD 弹性分布式数据集
//1. 创建 RDD 
w1: 来自一个内存中的对象集合
w2: 使用外部存储器的数据集
w3: 对现有RDD进行转换
val p = sc.parallelize(1 to 10)
val result = p.map(performExpensiveComputation)
sc.parallelize(1 to 10,10) 				//传送并行度
sc.textFile(inputPath,10)				//请求特定的分割数量
//通过返回一个字符串对RDD来把文本文件作为一个完整的文件(这种方法适用于小文件)
val files:RDD[(String,String)]=sc.wholeTextFiles(inputPath)
// 2. 转换和动作
RDD两大类操作:转换(惰性)和动作 
val text = sc.textFile(inputPath)
val lower:RDD[String] = text.map(_.toLowerCase())
lower.foreach(println(_))

///saprk中的mapreduce
map:		(K1,V1) -> list(K2,V2)
reduce:		(k2,list(V2)) -> list(K3,V3)

val l =List(1,2,3)
scala> l.map(a=>List(a))			--->res1: List[List[Int]] = List(List(1), List(2), List(3))
scala> l.flatMap(a=>List(a))			--->res2: List[Int] = List(1, 2, 3)
//在Spark中模拟MapReduce
val input:RDD[(K1,V1)] = ...
val mapOutput:RDD[(K2,V2)] = input.flatMap(mapFn)
val shuffled:RDD[(K2,Iterable[V2])] = mapOutput.groupByKey().sortByKey()
val output:RDD[(K3,V3)] = shuffled.flatMap(reduceFn)

///saprk 的聚合转换 reduceByKey,foldByKey,aggregateByKey
//1. reduceByKey
val pairs:RDD[(String,Int)] = sc.parallelize(Array(("a",1),("a",2),("b",1),("c",1),("a",1)))
val sums:RDD[(String,Int)] = pairs.reduceByKey(_+_)
assert(sums.collect().toSet === Set(("a",9),("b",7)))
//2. foldByKey
val sums:RDD[(String,Int)] = pairs.foldByKey(0)(_+_)	//0为初始累加值
assert(sums.collect().toSet === Set(("a",9),("b",7)))
//3. aggregateByKey
val pairs:RDD[(String,HashSet[Int])] = pairs.aggregateByKey(new HashSet[Int])(_+=_,_++=_)
assert(sums.collect().toSet === Set( ("a",Set(1,3,5)),("b",Set("7"))))

///共享变量
val lookup = Map(1->"a",2->"b",3->"c")
val result = sc.parallelize(Array(2,1,3)).map(lookup(_))
assert(result.collect().toSet === Set("b","a","c"))
//广播变量(作用类似与MR中的分布式缓存) 两者不同之处在于saprk将数据保存在内存中,只有内存耗尽才会溢出到磁盘上
//	https://www.jianshu.com/p/3bd18acd2f7f
//use the SparkContext.broadcast()
val lookup:Broadcast[Map[Int,String]] = sc.broadcast(Map(1->"a",2->"b",3->"c"))
val result = sc.parallelize(Array(2,1,3)).map(lookup.value(_))
assert(result.collect().toSet === Set("b","a","c"))

//累加器 (accumulator)
val count:Accumulator[Int]=sc.accumulator(0)
val result = sc.parallelize(Array(1,2,3)).map(i=>{count += 1;i}).reduce((x,y)=>x+y)
assert(count.value === 3)
assert(result === 6)

//一个简单的文本文件计算词频统计分布图
val hist:Map[Int,Long] = 
	sc.textFile(inputPath)
			.map(word=>(word.toLowerCase(),1))
			.reduceByKey((a,b)=>a+b)
			.map(_.swap)
			.countByKey()

val a =sc.textFile("/home/lufax/桌面/t.txt")

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值