scala入门基础
2018-12-19 本文已影响0人
kangapp
-
scala下载和安装
命令行使用
- JAVA8环境
- scala下载
- unzip scala
- 配置环境变量
- 启动 ./scala
基本数据类型
和java类型一致
- var 和 val
var 变量
val 常量 - asInstanceOf[数据类型]
类型转换函数 - isInstanceOf[数据类型]
判断是否是某一数据类型 - lazy
修饰符,延迟加载
Scala函数
- 方法的定义和使用
def 函数名(参数名:参数类型):函数返回值类型 = {函数体,最后一行为返回值,不需要return,只有一行可不加大括号}
无参函数调用可直接使用函数名 - 默认参数
(参数名:参数类型 = 默认参数) - 命名参数
调用函数的时候根据名字调用参数,可以不按顺序 - 可变参数
(参数名:参数类型*) - 循环表达式
to:(1 to 10)、(1.to(10))两种用法,包含始末;
until:用法同to,不包含末尾;
Range:Range(start, end, step)
for(x <- 1 to 10 if x % 2 == 0) {
println(x)
}
val courses = Array("hadoop", "spark", "mapreduce", "hive")
for(course <- courses){
println(course)
}
courses.foreach(x => {
println(x + 1)
})
var (num, sum) = (100,0)
while(num>0){
sum = sum + num
num = num -1
}
println(sum)
- yield
/**
* 针对每一次 for 循环的迭代, yield 会产生一个值,被循环记录下来 (内部实现上,像是一个缓冲区).
* 当循环结束后, 会返回所有 yield 的值组成的集合.
* 返回集合的类型与被遍历的集合类型是一致的.
*/
val a = Array(1,2,3,4,5)
val ret = for(e <- a) yield {
println(e)
e * 2
}
ret.foreach(println)
scala 对象
scala 集合
- 定长数组
val a = new Array[String](5)
a(1) = "hello"
println(a(1))
val b = Array("hello", "world", "are", "you", "ok")
for(x <- b){
println(x)
}
val c = Array(1, 2, 3, 4, 5)
println(c.sum)
println(c.max)
println(c.mkString("(",",",")"))
- 变长数组
val c = scala.collection.mutable.ArrayBuffer[Int]()
c += 1
c += (2, 3, 4)
c ++= Array(5, 6, 7)
c.insert(0, -2, -1, 0)
c.remove(0,3)
c.trimEnd(2) //从末尾移除
val d = c.toArray
- List
val a = Nil //Nil是空的List
//List 由head和tail组成
val b = List(1,2,3,4,5) //定长List
val c = 1 :: Nil
val d = 1::3::5::Nil
println(d.head+d.tail.mkString)
val e = scala.collection.mutable.ListBuffer[Int]() //变长List
e += (1,2,3) //和可变数组用法一致
e -= (2,3)
println(e.head)
println(e.tail) //ListBuffer类型
def sum(nums: Int*):Int = {
if(nums.length == 0){
0
} else {
nums.head + sum(nums.tail:_*) //递归操作,:_*将某个参数当做参数序列处理
}
}
- Set
//和上述类型用法一致,有定长和变长
val a = Set(1,2,3,4,5)
val b = scala.collection.mutable.Set[Int]()
b += 4
println(b.toList.length)
- Map
/**
* Map初始化的两种方式
*/
val m1 = Map(("name", "Tom"), ("age", 18))
val m2 = Map("name"->"Tom", "age"->18)
/**
* map get返回Option类型对象:Some或NONE
* 有下列三种获取方式,可以当做集合处理
*/
val o = m2.get("name")
println(o.getOrElse("no value"))
o match {
case Some(o) => println(o)
case None => println("no value")
}
o.foreach(println)
println(m2("name")) //直接获取map key对应的value,会抛出异常
println(m2.getOrElse("name","no value"));
/**
* 不可变Map,返回新的Map
*/
m2 + ("address"->"广州")
val m3 = m1 + ("hobby" -> "篮球", "job" -> "程序员")
m2 ++ m1
//m2 - ("hobby","job")
m2 -- m1.keySet //接收key的集合
m3.keysIterator.foreach(x => println("key: "+ x + "; value: "+ m3(x)))
val m = scala.collection.mutable.Map[String,Int]("A"->100, "B"->90)
/**
* 新增和移除和其它可变集合一致
*/
m += ("C" -> 70)
m += ("D" -> 60, "F" -> 50)
m ++= Map("E" -> 80)
m --= m1.keySet
m.keysIterator.foreach(x => println("key: "+ x + "; value: "+ m(x)))
/**
* 作缓存
*/
val cache = collection.mutable.Map[String, String]()
def f = (s: String) => {
print("waste my time"); Thread.sleep(1000)
s.reverse
}
def cacheF = (s:String) => cache.getOrElseUpdate(s, f(s))
println(cacheF("abc"))
println(cacheF("abc")) //第二次调用因为是相同的name,所以直接从map中取值
- Tuple
val tuple = ("scala", 1)
println(tuple._1)
println(tuple._2)
//支持解构
val (course, score) = tuple
println(course)
println(score)
//支持模式匹配
val planetDistanceFromSun = List(("Mercury", 57.9), ("Venus", 108.2), ("Earth", 149.6 ), ("Mars", 227.9), ("Jupiter", 778.3))
planetDistanceFromSun.foreach{ tuple => {
tuple match {
case ("Mercury", distance) => println(s"Mercury is $distance millions km far from Sun")
case p if(p._1 == "Venus") => println(s"Venus is ${p._2} millions km far from Sun")
case p if(p._1 == "Earth") => println(s"Blue planet is ${p._2} millions km far from Sun")
case _ => println("Too far....")
}
}
}
//循环表达式
val numPairs = List((2, 5), (3, -7), (20, 56))
for ((a, b) <- numPairs) {
println(a * b)
}
类和对象
- 类和属性的定义
package com.test
class ScalaClass {
//val 修饰的属性,系统会自动生成get方法
val id:String = "123456"
//var 修饰的属性,系统会自动生成get和set方法
var name:String = ""
//private var修饰的属性,系统会自动生成private修饰的get和set方法
private var gender_ :Int = 0
//私有成员的get和set方法,set方法为get函数名加上‘_=’,后面加上参数
def gender = gender_
def gender_=(newValue: Int) = {
if(newValue < 18){
println("你是未成年")
gender_ = newValue
} else{
println("成年人不许进入")
}
}
//只有当前对象可以访问该属性
private[this] var age:Int = 32
//不是当前对象,第四种会提示报错
def getGender(cla: ScalaClass) :Int = {
cla.gender_
}
def getAge():Int = {
age
}
}
object test {
def main(args: Array[String]): Unit = {
val cla = new ScalaClass()
cla.name = "tom"
/**
*需实现上面的get和set方法才能调用下面的set操作
*/
cla.gender = 17
println("name: "+cla.name+" id: "+cla.id+" gender: "+cla.getGender(cla)+" age: "+cla.getAge())
}
}
- 构造函数
package com.test
/**
* 类自带无参的构造函数
* 主构造函数执行类中所有的语句
* 构造函数分为主构造函数和辅助构造函数
*/
class ConstructClass {
var a:Int = 0
println("hello world")
//定义辅助构造函数
def this(a1:Int){
//辅助构造函数必须调用主构造函数或其他辅助构造函数
this()
this.a = a1
}
}
/**
* 定义带参的主构造函数,带var的参数是类的属性,不带则是普通的参数
* 带private则是私有构造函数
*/
class ConstructClass1 private (var b1:Int) {
var a:Int = 0
println("hello world")
//定义辅助构造函数
def this(a1:Int, b1:Int){
//辅助构造函数必须调用主构造函数或其他辅助构造函数
this(b1)
this.a = a1
}
}
object testConstruct{
def main(args: Array[String]): Unit = {
val cla = new ConstructClass(3)
val cla1 = new ConstructClass1(2,3)
println(cla.a)
}
}
- 单例对象和伴生对象
/**
* 单例对象,只初始化一次
* 可作工具类使用
*/
object ObjectClass {
def showInfo (msg: String)= {
println(s"message info: $msg")
}
}
class InfoClass {
def useObjectClass(msg:String) = {
ObjectClass.showInfo(msg)
}
}
object testObject {
def main(args: Array[String]): Unit = {
ObjectClass.showInfo("hello")
def obj = new InfoClass()
obj.useObjectClass("bye")
}
}
import scala.math._
/**
* 伴生类和伴生对象
* 可以互相访问彼此的私有属性和方法
*/
class ObjectClass(radius: Double){
import ObjectClass._
def area: Double = calculateArea(radius)
}
object ObjectClass{
private def calculateArea(radius: Double) = Pi * pow(radius, 2.0)
}
object testObject{
def main(args: Array[String]): Unit = {
val obj = new ObjectClass(5.0)
println(obj.area)
}
}
- apply和unapply
/**
* apply和unapply方法
*/
class User(val name:String, val password:String){
}
object User{
//创建对象不需要new,直接会调用apply方法
def apply(name:String, password:String) = new User(name, password)
//模式匹配会调用unapply方法,返回所需字段
def unapply(arg: User): Option[(String, String)] = {
if(arg == null){
None
} else{
Some(arg.name,arg.password)
}
}
}
object ApplyTest {
def main(args: Array[String]): Unit = {
val obj = User("tom","123456")
println(obj.name+":"+obj.password)
obj match {
case User(name, password) => println(name+":"+password)
case _ => println("none")
}
}
}
- 继承
object extendTest {
def main(args: Array[String]): Unit = {
val obj = new Location(1,11,2)
val obj1 = new Point(1,2)
println(obj.isInstanceOf[Point])
println(obj.isInstanceOf[Location])
}
}
class Point(val xc :Int, val yc :Int){
var x:Int = xc
var y:Int = yc
def move(dx:Int, dy:Int ): Unit ={
x = x + dx
y = y + dy
println("x 坐标:"+ x)
println("y 坐标:"+ y)
}
}
/**
* 继承了父类的所有属性和方法
* 重写父类的非抽象方法,要用override
* 重写父类的抽象方法,override可选择
*/
class Location(override val xc:Int,override val yc:Int, val zc:Int) extends Point(xc, yc){
var z:Int = zc
override def move(dx: Int, dy: Int): Unit = super.move(dx, dy)
def move(dx:Int, dy:Int, dz:Int): Unit ={
x = x + dx
y = y + dy
z = z + dz
println("x 坐标:"+ x)
println("y 坐标:"+ y)
println("z坐标:"+ z)
}
}
- 特质
/**
* 带有抽象方法的特质
*/
trait Iterator[A]{
val num:Int
def hasNext:Boolean
def next:A
}
/**
*带有实现的特质
*/
trait InfoLogger{
def showLog(msg:String): Unit ={
println(msg)
}
}
//类可以继承多个特质
class IntIterator(val to: Int) extends Iterator[Int] with InfoLogger {
private var current:Int = 0
override val num: Int = to
override def hasNext: Boolean = to > current
override def next: Int = {
if(hasNext){
showLog("still hasNext")
val t = current
current += 1
t
} else{
0
}
}
}
object TraitTest {
def main(args: Array[String]): Unit = {
val obj = new IntIterator(10)
println(obj.next)
println(obj.next)
println(obj.next)
println(obj.next)
println(obj.next)
println(obj.next)
}
}
trait Info{
def log(msg: String)
}
trait ConsoleInfo extends Info{
override def log(msg: String): Unit = {
println(msg)
}
}
//给日志加上时间戳
trait ConsoleTimeInfo extends ConsoleInfo{
override def log(msg: String): Unit = super.log(s"${java.time.Instant.now}$msg")
}
//截取一定长度的日志
trait ConsoleShorterInfo extends ConsoleInfo{
val length:Int = 15
override def log(msg: String): Unit = {
super.log(
if(msg.length <= length)
msg
else
s"${msg.substring(0, length)}"
)
}
}
class Account{
protected var balance:Double = 0.0
}
class SavingAccount extends Account with ConsoleInfo{
def withdraw(amount: Double): Unit ={
if(amount>balance) log("hello you are welcome")
else balance = balance - amount
}
}
/**
* 特质可以为类提供可堆叠的改变
* super方法可以从右往左往上调
*/
object TraitTest {
def main(args: Array[String]): Unit = {
val acc = new SavingAccount with ConsoleShorterInfo with ConsoleTimeInfo
acc.withdraw(20.0)
}
}
- 样例类
object CaseClassDemo {
def main(args: Array[String]): Unit = {
/**
* 定义样例类
* 默认带有apply方法
* 构造函数的参数默认是public val修饰的
*/
case class Message(title:String, body:String)
//创建一个样例类对象
val message = Message("hello", "world")
println(message.title+":"+message.body)
//样例类的比较是基于值进行比较的
val message1 = Message("hello", "world")
println(message == message1)
//样例类的copy
val message2 = message1.copy()
//不完全copy
val message3 = message.copy(title = "hi")
}
}
模式匹配
- 基本模式匹配
val subjects = Array("Hadoop", "Spark", "Flink")
val subject = subjects(Random.nextInt(subjects.length))
subject match {
case "Hadoop" => println("学习Hadoop")
case "Spark" => println("学习Spark")
case _ => println("不知道你在学习什么")
}
- 加条件模式匹配
def jdugeGrade(age:Int, grade:Char): Unit = {
grade match {
case 'A' => println("you are excellent")
case 'B' => println("you are grate")
case 'C' => println("you are good")
case _ if(age > 18) => println("i don not know how you study")
case _ => println("you need word harder")
}
}
- Array模式匹配
def greeting(array:Array[String]): Unit ={
array match {
case Array("zhangsan") => println("hello 张三")
case Array(x,y) => println("hello "+ x +" and "+ y)
case Array("zhangsan", _*) => println("hello zhangsan and others")
case _ => println("hello everybody")
}
}
- List模式匹配
def greeting(list:List[String]): Unit ={
list match {
case Nil => println("there are nobody here")
case "zhangsan"::Nil => println("hello zhangsan")
case x::y::Nil => println("hello "+ x + " and "+ y)
case "zhangsan"::tail => println("hello zhangsan and others")
case _ => println("hello everybody")
}
}
- 类型匹配
def matchType(obj:Any): Unit ={
obj match {
case x: Int => println("Type int")
case x: Float => println("Type float")
case x: Map[_, _] => {
x.keys.foreach(i => {
println("key: " + i)
println("value: " + x(i))
})
}
case _ => println("other Type")
}
}
matchType(Map("name"->"zhangsan", "age"->15, "adress"->"广东省广州市"))
- 异常处理
scala高级函数
- 字符串高级操作
/**
* 字符串连接
*/
val name = "zhangsan"
println(s"hello,$name")
/**
* 多行显示
* 按三次 shift+‘""’会自动出现
*/
val sentence =
"""
|hello
|hi
|how are you
""".stripMargin
println(sentence)
- 匿名函数
val functionA = (x:Int, y:Int) => x+y
def functionB = (name:String, age:Int) => {
println(s"my name is $name, I am $age years old")
}
println(functionA(2,3))
functionB("zhangsan", 18)
- 部分参数函数
/**
* 部分参数函数
*/
//定义一个主函数
def somebodySay = (somebody:String, word: String) => {
println(somebody+" : "+word)
}
//部分参数函数
def tomSay = somebodySay("Tom", _:String)
def marySay = somebodySay("mary", _:String)
tomSay("hello , mary")
- 方法的嵌套和多态
/**
* 方法的嵌套和多态
*/
//方法嵌套:求阶乘
def outFun(x: Int): Int ={
def inFun(x:Int, y: Int): Int ={
if(x<=1) y
else inFun(x-1,x*y)
}
inFun(x,1)
}
println("10的阶乘: "+outFun(10))
//方法多态:通过类型实现参数化,类似泛型
def createList[A](x: A, length:Int):List[A] = {
if(length<1)
Nil
else
x::createList(x, length-1)
}
println(createList[Int](4,10))
高阶函数*
- map
/**
* map:逐个去操作集合中的元素
*/
val array = Array(1, 2, 3, 4, 5)
array.map(x => x*2).foreach(println)
array.map(_ + 2).foreach(println)
- filter
/**
* filter:返回符合条件的元素集合
*/
val list = List(1, 3, 5, 7, 9)
list.map(x => x+2).filter(x => x>8).foreach(println)
list.map(_ * 2).filter(_ > 8).foreach(println)
- reduce和folder
/**
* reduce:对集合的元素两两进行操作,默认是Left
* fold:相较于reduce,多了初始值
*/
val list = List(2, 4, 6, 8, 10)
println(list.reduce((x, y) => x + y))
println(list.reduce(_ - _))
println(list.reduceRight(_ - _))
println(list.fold(10)(_ - _))
- flatten 和 flatmap
/**
* flatten:把嵌套的结构打开
*/
List(List(1,3), List(5,8)).flatten.foreach(println)
Array("hello", "hi").flatten.foreach(println)
/**
* flatMap:结合map和flatten的功能
*/
List(List("hello","hi"),List("thinks", "good job")).flatMap(_.map(_+", jack")).foreach(println)
scala隐式类
- 简单使用
//隐式类的简单引用,把File类隐式转化为RichFile类
implicit class RichFile(from: File) {
def read:String = Source.fromFile(from.getPath).mkString
}
val content = new File("src/test.txt").read
println(content)
- 隐式类
package com.test
object ImplicitClass {
/**
* 定义一个隐式类
* 隐式类只能定义在类、trait、object内部
* 隐式类的构造函数只能带一个非隐式参数
*/
implicit class IntWithTimes(x:Int){
def times[A](f: =>A) = {
//递归方法需要显式指明返回类型
def loop(current:Int):Unit = {
if(current>0){
f
loop(current-1)
}
}
loop(x)
}
}
}
package com.test
import ImplicitClass._
object ImplicitTest extends App {
10 times(println("success"))
}
- 隐式转换函数
//定义一个隐式转换函数,把double转为Int
implicit def doubleToInt(x: Double) = x.toInt
var a: Int = 10
var b: Double = 10.99
//加上隐式转换函数之后编译通过,编译器会自动寻找合适的隐式转换函数
a = b