yield会把当前元素给记录下来,并保存到集合中
val v = for(i <- 1 to 10) yield i * 10
println(v)
结果:
Vector(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
var修饰的变量是可变的,val是不可变的
package com.xu
import scala.util.control.Breaks._
object ScalaTest {
def main(args: Array[String]): Unit = {
breakable {
for(i <- 1 to 10) {
if(i >= 5)
break()
else
println(i)
}
}
}
}
package com.xu
import scala.util.control.Breaks._
object ScalaTest {
def main(args: Array[String]): Unit = {
for(i <- 1 to 100) {
breakable {
if(i % 10 == 0)
break()
else
println(i)
}
}
}
}
val 函数变量名 = (参数名:参数类型, 参数名:参数类型…) => 函数体
val add = (x:Int, y:Int) => x + y
def main(args: Array[String]): Unit = {
println(add(1,2))
}
方法无法赋值给一个变量,但是 函数可以赋值给一个变量,那么先将方法转为一个函数:
val add = (x:Int, y:Int) => x + y
def main(args: Array[String]): Unit = {
val a = add _
}
定义变长数据,可加/减/追加
使用+=添加元素
使用-=删除元素
使用++=追加一个数组到变长数组
package com.xu
import scala.collection.mutable.ArrayBuffer
object ScalaTest {
def main(args: Array[String]): Unit = {
val a = ArrayBuffer("hadoop", "storm", "spark")
a += "fluem"
println(a)
}
}
val a = Array(5 to 10)
for(i <- 0 to a.length - 1)
println(a(i))
元组可以用来包含一组不同类型的值。例如:姓名,年龄,性别,出生年月。元组的元素是不可变的
val a = (1, "zhangsan", 20, "beijing")
println(a._1)
println(a._2)
列表是scala中最重要的、也是最常用的数据结构。List具备以下性质:
可以保存重复的值
有先后顺序
使用::拼接方式来创建列表,必须在最后添加一个Nil
不可变列表创建:
val a = List(1,2,3,4)
val a = -2 :: -1 :: Nil
可变列表创建及操作:
package com.xu
import scala.collection.mutable.ListBuffer
object ScalaTest {
def main(args: Array[String]): Unit = {
val a = ListBuffer[Int]()
val b = ListBuffer(1,2,3,4)
println(a += 4) //追加一个元素
println(a ++= List(9,8,7)) //追加一个列表
println(a -= 4) // 删除元素
println(a.toList) // 转换为不可变列表
println(a.toArray) // 转换为数组
}
}
val a = List(1,2,3,4,5)
println(a.head) //获取头
println(a.tail) //获取除第一个元素以外的元素,它也是一个列表
println(a.reverse) //反转列表
println(a.take(3)) //获取前三个元素
println(a.drop(3)) //除去前三个的元素
val b = List(List(1,2), List(3), List(4,5))
println(b.flatten) //扁平化
导入对应的包,就是可变的
import scala.collection.mutable.Set
import scala.collection.mutable.Map
package com.xu
object ScalaTest {
class Person {
val name = "super"
def getName = name
}
class Student extends Person {
// 重写val字段 子类要覆盖父类中的一个方法,必须要使用override关键字
override val name: String = "child"
// 重写getName方法
override def getName: String = "hello, " + super.getName
}
def main(args: Array[String]): Unit = {
println(new Student().getName)
}
}
isInstanceOf判断对象是否为指定类的对象
asInstanceOf将对象转换为指定类型
package com.xu
object ScalaTest {
class Person3
class Student3 extends Person3
def main(args: Array[String]): Unit = {
val s1:Person3 = new Student3
if(s1.isInstanceOf[Student3]) {
var s2 = s1.asInstanceOf[Student3]
println(s2)
}
}
}
isInstanceOf 只能判断对象是否为指定类以及其子类的对象,而不能精确的判断出,对象就是指定类的对象。如果要求精确地判断出对象就是指定类的对象,那么就只能使用 getClass 和 classOf
package com.xu
object ScalaTest {
class Person3
class Student3 extends Person3
def main(args: Array[String]): Unit = {
val p:Person3 = new Student3
println(p.getClass == classOf[Person3])
println(p.getClass == classOf[Student3])
}
}
package com.xu
object ScalaTest {
abstract class Person {
def sayHell:Unit
}
def main(args: Array[String]): Unit = {
val p1 = new Person {
override def sayHell: Unit = println("我是一个内部类")
}
p1.sayHell
}
}
使用extends来继承trait(scala不论是类还是特质,都是使用extends关键字)
如果要继承多个trait,则使用with关键字
package com.xu
object ScalaTest {
trait Logger {
def log(message:String)
}
class ColsoleLogger extends Logger {
override def log(message: String): Unit = println("控制台打印:" + message)
}
def main(args: Array[String]): Unit = {
val logger = new ColsoleLogger
logger.log("hahha")
}
}
package com.xu
object ScalaTest {
trait LoggerDate {
def log(msg:String) = println("打印:" + msg)
}
class UserService extends LoggerDate {
def add() = log("添加用户")
}
def main(args: Array[String]): Unit = {
val userService = new UserService
userService.add()
}
}
要实现以下需求:
实现一个输出日志的功能
目前要求输出到控制台
将来可能会输出到文件、输出到Redis、或者更多的需求
package com.xu
object ScalaTest {
trait Logger {
def log(msg:String)
def info(msg:String) = log("info级别:"+msg)
def warn(msg:String) = log("warn级别:" + msg)
}
class ConsoleLogger extends Logger {
override def log(msg: String): Unit = {
println(msg)
}
}
def main(args: Array[String]): Unit = {
val logger = new ConsoleLogger
logger.info("信息日志")
logger.warn("警告日志")
}
}
类继承了多个trait后,可以依次调用多个trait中的同一个方法,只要让多个trait中的同一个方法在最后都依次执行super关键字即可。类中调用多个tait中都有这个方法时,首先会从最右边的trait方法开始执行,然后依次往左执行,形成一个调用链条。
步骤
定义一个HandlerTrait特质
定义一个具体的handler方法,打印"处理数据…"
定义一个DataValidHandlerTrait,继承HandlerTrait特质
重写handler方法,打印"验证数据"
调用父特质的handler方法
定义一个SignatureValidHandlerTrait,继承HandlerTrait特质
重写Handler方法
打印"检查签名"
调用父特质的handler方法
创建一个PaymentService类
继承DataValidHandlerTrait
继承SignatureValidHandlerTrait
定义pay方法
打印"准备支付"
调用父特质的handler方法
添加main方法
创建PaymentService对象实例
调用pay方法
package com.xu
object ScalaTest {
trait HandlerTrait {
def handle(data:String) = println("5.处理数据....")
}
trait DataValidHanlder extends HandlerTrait {
override def handle(data: String): Unit = {
println("4.验证数据....")
super.handle(data)
}
}
trait SignTureValidHandler extends HandlerTrait {
override def handle(data: String): Unit = {
println("3.校验签名....")
super.handle(data)
}
}
//这里的继承顺序,执行父级的及执行顺序,现有写法,先执行sign中的
class PayService extends DataValidHanlder with SignTureValidHandler {
override def handle(data: String): Unit = {
println("2.准备支付....")
super.handle(data)
}
}
def main(args: Array[String]): Unit = {
val service = new PayService
service.handle("开始啦!!")
}
}
样例类是一种特殊类,它可以用来快速定义一个用于保存数据的类(类似于Java POJO类),在后续要学习并发编程和spark、flink这些框架也都会经常使用它。
package com.xu
object ScalaTest {
case class Person(name:String, age:Int)
def main(args: Array[String]): Unit = {
val zhangsan = Person("张三", 20)
println(zhangsan)
}
}
获取数组中的元素
val array = (1 to 10).toArray
val Array(_, x, y, z, _*) = array
println(x, y, z)
获取List中的数据
val list = (1 to 10).toList
val x :: y :: tail = list
println(x, y)
使用Option类型,可以用来有效避免空引用(null)异常。也就是说,将来我们返回某些数据时,可以返回一个Option类型来替代。
package com.xu
import scala.io.StdIn
object ScalaTest {
def div(a:Double, b:Double) : Option[Double] = {
if(b != 0) {
Some(a / b)
} else {
None
}
}
def main(args: Array[String]): Unit = {
val reslut = div(1.0, 2.0)
reslut match {
case Some(x) => println("不是None")
case None => println("这个是none啊")
}
}
}
使用getOrElse方法,当除零时,或者默认值为0
def dvi(a:Double, b:Double) = {
if(b != 0) {
Some(a / b)
}
else {
None
}
}
def main(args: Array[String]): Unit = {
val result = dvi(1, 0).getOrElse(0)
println(result)
}
偏函数被包在花括号内没有match的一组case语句是一个偏函数
偏函数是PartialFunction[A, B]的一个实例
A代表输入参数类型
B代表返回结果类型
// func1是一个输入参数为Int类型,返回值为String类型的偏函数
val func1: PartialFunction[Int, String] = {
case 1 => "一"
case 2 => "二"
case 3 => "三"
case _ => "其他"
}
println(func1(2))
try {
val i = 10 / 0
println("你好!")
} catch {
case ex: Exception => println(ex.getMessage)
}
样例类自动实现了apply、unapply方法
另外伴生对象中,要实现一个类的提取器,只需要在该类的伴生对象中实现一个unapply方法即可
class Student(var name:String, var age:Int)
object Student {
def apply(name:String, age:Int) = {
new Student(name, age)
}
def unapply(student:Student) = {
val tuple = (student.name, student.age)
Some(tuple)
}
}
def main(args: Array[String]): Unit = {
val zhangsan = Student("张三", 20)
zhangsan match {
case Student(name, age) => println(s"${name} => ${age}")
}
}
不同类型集合,求中间值
def getMiddleElement[T](array:Array[T]) =
array(array.length / 2)
def main(args: Array[String]): Unit = {
println(getMiddleElement(Array(1, 2, 3, 4, 5)))
println(getMiddleElement(Array("a", "b", "c", "d", "e")))
}
val r = """.+@.+\..+""".r
val eml1 = "[email protected]"
val eml2 = "[email protected]"
if(r.findAllMatchIn(eml1).size > 0) {
println(eml1 + "邮箱合法")
}
else {
println(eml1 + "邮箱不合法")
}
if(r.findAllMatchIn(eml2).size > 0) {
println(eml2 + "邮箱合法")
}
else {
println(eml2 + "邮箱不合法")
}
val emlList =
List("[email protected]", "[email protected]", "[email protected]", "123afadff.com")
val regex = """.+@.+\..+""".r
val invalidEmlList = emlList.filter {
//返回结果为ture的 ,即输出合法的邮箱有那些,
x => if (regex.findAllMatchIn(x).size > 0) true else false
}
println(invalidEmlList)
匹配邮件的所属机构:
// 使用括号表示一个分组
val regex = """.+@(.+)\..+""".r
val emlList =
List("[email protected]", "[email protected]", "[email protected]", "123afadff.com")
val emlCmpList = emlList.map {
//匹配是倒数第一位点
case x@regex(compan) => s"${x} => ${compan}"
case x => x + "=>未知"
}
case class Pair[T](var a:T, var b:T)
def main(args: Array[String]): Unit = {
val pairList = List(
Pair("Hadoop", "Storm"),
Pair("Hadoop", 2008),
Pair(1.0, 2.0),
Pair("Hadoop", Some(1.9))
)
println(pairList)
}
需求:
我们在定义方法/类的泛型时,限定必须从哪个类继承、或者必须是哪个类的父类。此时,就需要使用到上下界。
class Person
class Student extends Person
def demo[T <: Person](a:Array[T]) = println(a)
def main(args: Array[String]): Unit = {
demo(Array(new Person))
demo(Array(new Student))
// 编译出错,必须是Person的子类
// demo(Array("hadoop"))
}
class Person
class Policeman extends Person
class Superman extends Policeman
def demo[T >: Policeman](array:Array[T]) = println(array)
def main(args: Array[String]): Unit = {
demo(Array(new Person))
demo(Array(new Policeman))
// 编译出错:Superman是Policeman的子类
// demo(Array(new Superman))
}
让带有泛型的类支持类型转换
class Super
class Sub extends Super
class Temp1[T] // 非变
class Temp2[+T] // 协变
class Temp3[-T] // 逆变
def main(args: Array[String]): Unit = {
val a:Temp1[Sub] = new Temp1[Sub]
// 编译报错
// 非变
//val b:Temp1[Super] = a
// 协变 类型B是A的子类型,Pair[B]可以认为是Pair[A]的子类型
val c: Temp2[Sub] = new Temp2[Sub]
val d: Temp2[Super] = c
// 逆变 类型B是A的子类型,Pair[A]反过来可以认为是Pair[B]的子类型
val e: Temp3[Super] = new Temp3[Super]
val f: Temp3[Sub] = e
}