string操作
object stringtest extends App {
val age = 23
println(s"age equal $age")
case class student(name: String)
val student1 = new student("rual")
println(s"student1 names is ${student1.name}") // 前面的s标识可以引用变量
val weight = 23
println(f"${student1.name} is $age years old, and weighs $weight%.2f pounds.") //前面f格式化输出
println(raw"foo\nbar") //前面raw表示不换行
val address = "123 Main Street".replaceAll("[0-9]", "x")
println(address)
val regex = "[0-9]".r
val newaddress = "No address given"
val result = regex.findFirstIn(newaddress).getOrElse("no match")
println(result)
val pattern = "([0-9]+) ([A-Za-z]+)".r
val pattern(count, fruit) = "100 Bananas" //直接产生两个常量 count=100,fruit =Banaas 如果不匹配会报错
println(count)
println(fruit)
// match "movies 80301"
val MoviesZipRE = "movies (\\d{5})".r
// match "movies near boulder, co"
val MoviesNearCityStateRE = "movies near ([a-z]+), ([a-z]{2})".r
val textUserTyped = "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")
//为己知类型添加方法
object StringUtils {
implicit class StringImprovements(val s: String) {//修改的类型String
def increment = s.map(c => (c + 1).toChar)//增加的方法
}
}
import StringUtils._
println("HAL".increment)//IBM
}
}
structure相关
object structuretest extends App {
val a = Array("apple", "banana", "orange")
//for循环
for (e <- a) println(e)val newArray = for (e <- a) yield e.toUpperCase //循环中的内容产生值 Array(APPLE, BANANA, ORANGE)
val newArray1 = for (e <- a) yield { //等同上一句
val s = e.toUpperCase
s
}
//for其他写法
for (i <- 1 to 3) println(i)
for (i <- 1 to 10 if i < 4) println(i) //多个语句中间空格分隔
for (i <- 1 until 3) println(i)
val names = Map("fname" -> "Robert",
"lname" -> "Goren")
for ((k, v) <- names) println(s"key: $k, value: $v")
for {
i <- 1 to 2; j <- 2 to 3 //多个变量中间需要分号
} println(s"i = $i, j = $j")
//类型三目运算符
val v = 7
val absValue = if (v < 0) -v else a
//switch case语句
val month = 1 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)
}
//根据类型匹配
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 _ => "Unknown"
}
//匹配多个条件
val numbertype = 5 match {
case 1 | 3 | 5 | 7 | 9 => println("odd")
case 2 | 4 | 6 | 8 | 10 => println("even")
}
//匹配表达式
val x: Any = None
val expression = x match {
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"
}
//match中加入条件
1 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...")
}
//利用match代替if else
trait SentientBeingtrait Animal extends SentientBeing
case class Dog(name: String) extends Animal
case class Person(name: String, age: Int) extends SentientBeing
// later in the code ...
def printInfo(x: SentientBeing) = x match {
case Person(name, age) => // handle the Person
case Dog(name) => // handle the Dog
}
//创建自己的控制语句
def whilst(testCondition: => Boolean)(codeBlock: => Unit) {while (testCondition) {
codeBlock
}
}
var i = 0
whilst(i < 5) {//i<5 相当于testCondition 大括号中两行相当于codeBlock
println(i)
i += 1
}
class相关
object classtest extends App {
case class socket(val timeout: Int = 100, val linger: Int)
val s = socket(linger = 10) //根据参数名赋值
// s.timeout=20 会报错 val代表常量
case class socket1(var timeout: Int = 100, var linger: Int)
val s1 = socket1(linger = 10)
s1.timeout = 20 //不会报错 var代表变量
//修改scala pojo默认set get方法
class Person(private var _name: String) {def name = _name //get方法
def name_=(aName: String) { _name = aName } //set方法 方法名是scala約定,get方法名不能与变量名冲突,注意name_后面的等号不可缺少
}
val p = new Person("Jonathan")
p.name = "Jony"
println(p.name)
//初始化变量通这block lazy延时加载
lazy val text = {var lines = ""
try {
lines = io.Source.fromFile("/etc/passwd").getLines.mkString
} catch {
case e: Exception => lines = "Error happened"
}
lines
}
}
import 语句
object importtest extends App {
import java.io.{File, IOException, FileNotFoundException}//导入指定类
import java.io._//导入io下全部类
def importdef()={
import java.util._//随处可以import
}
import java.util.{Random => _}//导入util下所有,除了random
}
function相关
object functionaltest extends App {
//方法赋与变量
val double = (i: Int) => { i * 2 }double(2) // 4
double(3) // 6
//分配己有方法给一个变量
val c = scala.math.cos _c(0) //println 0
//方法接爱方法参数
def determineOdd(odd: () => Unit, even: () => Unit, condition: Int => Boolean, p: Int) = { //odd中的()只是一个占位符,表示没有参数if (condition(p)) {
odd()
} else {
even()
}
}
val printlnodd = () => println("odd")
val printlneven = () => println("even")
determineOdd(printlnodd, printlneven, number => number % 2 != 0, 23)
//閉包
class Foo {
def exec(f: (String) => Unit, name: String) {
f(name)
}
}
var hello = "Hello"
def sayHello(name: String) { println(s"$hello, $name") } //閉包感知hello name的變化
val foo = new Foo
foo.exec(sayHello, "Al") //Hello, Al
hello = "Hola"
foo.exec(sayHello, "Lorenzo") //Hola, Lorenzo
//Partially Applied Functions
val sum = (a: Int, b: Int, c: Int) => a + b + cval f = sum(1, 2, _: Int)
f(3) //print 6
//Partial Functions定义一个方法,并且这个方法仅接受参数类型的一个子集
val nums1 = Array("one", "two", "three", "four", "five")val convert1to5: PartialFunction[Int, String] = {//函數定義[Int,String] int輸入類型,string返回類型,case (t < 6 && t >0) 子集的條件
case t: Int if (t < 6 && t >0) => nums1(t)
}
val nums2 = Array("one", "two", "three", "four", "five")
val convert6to10: PartialFunction[Int, String] = {
case t: Int if (t <= 10 && t >= 6) => nums2(t)
}
val handle1to10 = convert1to5 orElse convert6to10// orelse 與 partical function聯合使用可以一直 orelse下去
println(handle1to10(3))
}
method相关
package com.acme.coolapp.model {
class Foo {
private[model] def doX {}
private def doY {}
}
class Bar {
val f = new Foo //scope属于model包
f.doX // compiles
// f.doY // won't compile 因为doY scope属于Foo
}
}
object methodtest extends App {
class Foo {
private[this] def isFoo = true
def doFoo(other: Foo) {
// if(other.isFoo)//报错private[this]控制访问scope
}
}
//方法返回多个值
def getStockInfo = {("NFLX", 100.00, 101.00)
}
val (symbol, currentPrice, bidPrice) = getStockInfo
//参数变长
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: _*) //传递list给printAll
//fluent style method
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
}
}
val p = new Person
p.setFirstName("fname").setLastName("lname") //可读性高一点,不用换行了
//scala强制转换
val anyArray: Array[Any] = Array(p, 2)anyArray(0).asInstanceOf[Person]
//scala T.class方法
val stringClass = classOf[String]for (m <- stringClass.getMethods)
println(m)
anyArray(0).isInstanceOf[Person] //相当于java instanceof
//scala companion object
//scala没有static关键字,怎样创建static method?class Pizza(var crustType: String) {
private val secret = 2
override def toString = "Crust type is " + crustType + Pizza.obj //可以访问companion obj私有变量
}
//Pizza companion object companion object与class必须在同一个文件中
object Pizza {
val CRUST_TYPE_THIN = "thin" //静态字段
val CRUST_TYPE_THICK = "thick"
def getFoo = "Foo"
def double(pizza: Pizza) = {
pizza.secret * 2 //访问class private field
}
private val obj = "visible"
def getInstance = new Pizza("john") //单例方法
}
println(Pizza.getInstance.toString())
//可以将一些包中公共的常量,方法放入package object中 package object需要单独创建一个文件
// package object scalatest {//val MAGIC_NUM = 42
//}
println(MAGIC_NUM)
//工厂方法
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 = { //apply方法是companion object的一個特列方法(injection method) 它對應一另一個方法unapply方法(extraction method)if (s == "dog") new Dog
else new Cat
}
val dog = Animal("dog")
}
// apply与unapply,apply相当于通过已有值构造对象,unapply相当于解析传入的值并且给对象字段赋值
class student(var id: String, var _name: String, var address: String) {def name = _name //get方法
def name_=(aName: String) { _name = aName + "a" }
}
object student {
def apply(id: String, name: String, address: String) = {
new student(id, name, address)
}
def unapply(line: String) = {
val parts = line.split(",")
if (parts.length == 3) Some(parts(0), parts(1), parts(2)) else None
}
}
val student(number, name, addr) = "B123456,Justin,Kaohsiung" //匹配unapply方法
println(number)
println(name)
val students = List(
"B123456,Justin,Kaohsiung",
"B98765,Monica,Kaohsiung",
"B246819,Bush,Taipei")
students.foreach(_ match {
case student(nb, name, addr) => println(nb + ", " + name + ", " + addr)
})
}
curry化
curry化的函数被应用了多个参数列表,而不是仅仅一个
def testcurry(i:Int)(s:String)(array:Array[Double])={
val result=new TestPojo()
result.i=i
result.s=s
result.array=array
result
}
class TestPojo() {
var i = 0
var s = ""
var array = Array[Double]()
override def toString = i +" "+ s +" "+ array(1)
}
测试
val test1=testcurry(1)("hello")(Array(0d,10d,20d))
println(test1.toString)
结果 1 hello 10.0
还可以这样
val test2=testcurry(1)_ //_ 相当于占位符
val test21=test2("world")
val test211=test21(Array(200d,300d))
println(test211)
个人感觉柯里化适合抽象过程
option使用
option在scala中可以避免nullpointexception
example
val o:Option[Int]=Some(1)
val o1:Option[Int}=None
o.getOrElse(0) // print 1
o1.getOrElse(0) //print 0
getOrElse两边还可以是function
example
def notNoneFunction()={
...
// return Some(Any)
}
def noneFunction()={
.....
return None
}
noneFunction.getOrElse(notNoneFunction) //print notNoneFunction
noneFunction getOrElse notNoneFunction //print notNoneFunction
打印出notNoneFunction结果,因为 noneFunction为None
上述两种写法意思相同
option 其他
val map=Map(1 -> User(Some("test")),2 -> User(None))
println(map.get(1).map { x => x.name })
println(map.get(2).map { x => x.name })
//x为none是输出none//不为none正常输出
Either and right and left
可以把Either想像为Option,right想像成为som,left想像成为None
但是他们有什么不同呢,使用option时我们可能无法告诉当None的时候发生了什么,读者只是看到 None getOrElse Some
object EitherLeftRightExample extends App {
def divideXbyY(x:int,y:int):Either[String,Int]={
if(y==0) Left("can't divide by 0")
else
Right(x/y)
}
case Left(s) => println("answer"+s)
case Right(a) => println("answer"+a+1)
}
}
可以看到这种方式可读性更高,可以返回不同类型的结果,即:Either[String,Int] String => Left(String), Int => Right(Int)
scala type
class Grandparent{}
class Parent extends Grandparent{}
class Child extends Parent{}
class InvariantClass[A] //[A]仅能匹配A类型
class CovariantClass[+A] //[+A]匹配A 及 A subclass
class ContravariantClass[-A] [+A]匹配A 及 A parent class
//class VarianceExamples {
def invarMethod(x: InvariantClass[Parent]) {}
def covarMethod(x: CovariantClass[Parent]) {}
def contraMethod(x: ContravariantClass[Parent]) {}
def boundType[S <: Child](s:S)={}
//invarMethod(new InvariantClass[Child]) // ERROR - won't compile
invarMethod(new InvariantClass[Parent]) // success
//invarMethod(new InvariantClass[Grandparent]) // ERROR - won't compile
covarMethod(new CovariantClass[Child]) // success
covarMethod(new CovariantClass[Parent]) // success
//covarMethod(new CovariantClass[Grandparent]) // ERROR - won't compile
//contraMethod(new ContravariantClass[Child])
contraMethod(new ContravariantClass[Parent])
contraMethod(new ContravariantClass[Grandparent])
scala 泛型写法
class LinkedList[A] { //[A]指定泛型
private class Node[A] (elem: A) {
var next: Node[A] = _
override def toString = elem.toString
}
private var head: Node[A] = _
def add(elem: A) {
val n = new Node(elem)
n.next = head
head = n
}
private def printNodes(n: Node[A]) {
if (n != null) {
println(n)
printNodes(n.next)
}
}
def printAll() { printNodes(head) }
}
trait Pair[A, B] {
def getKey: A
def getValue: B
}
scala中通常指定类型利用[]而不是java的<>
Structural Types
def callspeak[A <: {def speak() : Unit}](obj:A)={//参数type,传入的A对象必须有speak方法
obj.speak()
}
class Dog{def speak(){println("dog")}}
class Cat{def speak(){println("cat")}}
callspeak(new Dog)
将默认行为加入model或者说是方法
trait animal{
def speak
}
class dog extends animal{
def speak(){
println("dog")
}
}
class cat extends animal{
def speak(){
println("cat")
}
}
trait humanlike[A]{
def speak(speaker:A):Unit
}
object humanlike{
implicit object doghumanlike extends humanlike[dog]{
def speak(speaker:dog){
speaker.speak()
}
}
implicit object cathumanlike extends humanlike[cat]{
def speak(speaker:cat){
speaker.speak()
}
}
}
def makeHumanLikeThingSpeak[A](animal:A)(implicit humanlike:humanlike[A]){
humanlike.speak(animal)
}
makeHumanLikeThingSpeak(new dog)
其他scala type相关
class stack[A <: Child](elem:A) <:说明传入的A必须是child子类, 反之:>说明传入A必须是child父类
先介绍这么多,将不断更新