scala学习
时间: 2020-06-03来源:OSCHINA
前景提要
使用scala的开发的软件
spark , apache flink , kafka 等
scala 与java 区别例子 Scala vs Java HelloWorld public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World..."); } } Scala每行代码并不强求使用;结束,但是Java是必须的 object HelloWorld { def main(args : Array[String]) { println("Hello World...") } }
sacla 语法


数字类型转换

判断是否属于某个数字类型 val vs var val:值 final val 值名称:类型 = xxx var:变量 var 值名称:类型 = xxx Scala基本数据类型 Byte/Char Short/Int/Long/Float/Double Boolean
lazy

scala 函数 函数/方法的定义 def 方法名(参数名:参数类型): 返回值类型 = { // 括号内的叫做方法体 // 方法体内的最后一行为返回值,不需要使用return } 默认参数: 在函数定义时,允许指定参数的默认值 $SPARK_HOME/conf/spark-defaults.conf 可变参数: JDK5+ : 可变参数 循环表达式 to Range until
定义与使用

命名参数

调用参数可以顺序不一样
可变参数
即参数可以有任意多个 /** * 可变参数 ,可以有多个 类似 java 的 ... * @param numbers */ def sum(numbers:Int*): Unit ={
表达式
if else 等
循环表达式

def loop(): Unit ={ var num1 = 1 to 10 var num2 = 1.to(10) // 与 1 to 10 写法一样的 for (elem <- num1) { println(elem) } for( i <- 1 to 10 if i%2 == 0){ println(i) } val courses=Array("语文","数学") for (elem <- courses) { } courses.foreach(f => println(f)) courses.foreach(f => { println(f) } ) }

面向对象

占位符 _ 下划线,即 使用默认值,不赋值


类的定义与使用 package org.train.scala.c4 object SimpleApp { def main(args: Array[String]): Unit = { val person=new People(); person.name="ss" println(person.name+ person.age) person.eat() person.printInfo() } } class People{ //变量,自动生成 get /set 方法 var name="" var nick : String =_ //不可变常量,没有 get/set val age:Int = 10 def eat(): String={ name +"eat ..." } //只能在class 内可以访问,类外不可以 private [this] val gender="male" // [this] 可去掉: private val gender="male" def printInfo(): Unit ={ println(gender) } }
构造器 package com.imooc.scala.course04 object ConstructorApp { def main(args: Array[String]): Unit = { // val person = new Person("zhangsan", 30) // println(person.name + " : " + person.age + " : " + person.school) // // // val person2 = new Person("PK", 18, "M") // println(person2.name + " : " // + person2.age + " : " // + person2.school + " :" // + person2.gender // ) val student = new Student("PK", 18, "Math") println(student.name + " : " + student.major) println(student) } } // 主构造器 class Person(val name:String, val age:Int) { println("Person Constructor enter....") val school = "ustc" var gender:String = _ // 附属构造器 def this(name:String, age:Int, gender:String) { this(name, age) // 附属构造器的第一行代码必须要调用主构造器或者其他附属构造器 this.gender = gender } println("Person Constructor leave....") } class Student(name:String, age:Int, var major:String) extends Person(name, age) { println("Person Student enter....") //重写 override val school = "peking" override def toString: String = "Person: override def toString :" + school println("Person Student leave....") }
抽象类 abstract package org.train.scala.c4 object AbstractApp { def main(args: Array[String]): Unit = { new Stude2().speak; } } /** * 只有定义,没有实现 */ abstract class Person2{ //抽象方法 def speak //抽象的属性 val name:String } class Stude2 extends Person2{ override def speak: Unit = { println("sk") } override val name: String = _ }
伴生类和伴生对象 /** * 伴生类和伴生对象 * 如果有一个class,还有一个与class同名的object * 那么就称这个object是class的伴生对象,class是object的伴生类 */ //伴生类 (相对 object ApplyTest ) class ApplyTest{ } //伴生对象 (相对class ApplyTest 来说的 ) object ApplyTest{ }
apply 方法 package com.imooc.scala.course04 object ApplyApp { def main(args: Array[String]): Unit = { // for(i <- 1 to 10) { // ApplyTest.incr // } // // println(ApplyTest.count) // 10 说明object本身就是一个单例对象 val b = ApplyTest() // ==> Object.apply println("~~~~~~~~~~~") val c = new ApplyTest() println(c) c() // 类名() ==> Object.apply // 对象() ==> Class.apply } } /** * 伴生类和伴生对象 * 如果有一个class,还有一个与class同名的object * 那么就称这个object是class的伴生对象,class是object的伴生类 */ class ApplyTest{ def apply() = { println("class ApplyTest apply....") } } object ApplyTest{ println("Object ApplyTest enter....") var count = 0 def incr = { count = count + 1 } // 最佳实践:在Object的apply方法中去new Class def apply():ApplyTest = { println("Object ApplyTest apply....") // 在object中的apply中new class new ApplyTest } println("Object ApplyTest leave....") }
case class // 通常用在模式匹配 object CaseClassApp { def main(args: Array[String]): Unit = { println(Dog("wangcai").name) } } // case class不用new case class Dog(name:String) case class Dog2(name: String)
trait 接口 Java/Scala OO 封装:属性、方法封装到类中 Person: private int id, String name, Date birthday..... getter/setter eat、sleep.... 继承:父类和子类之间的关系 User extends Person exam..... 多态:***** 父类引用指向子类对象 精髓所在 开发框架的基石 Person person = new Person(); User user = new User(); Person person = new User(); Trait xxx extends ATrait with BTrait class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging with Serializable ... ....
集合
数组 package com.imooc.scala.course05 object ArrayApp extends App{ // val a = new Array[String](5) // a.length // a(1) = "hello" // // val b = Array("hadoop", "spark", "storm") // // val c = Array(2,3,4,5,6,7,8,9) // c.sum // c.min // c.max // // c.mkString(",") // 可变数组 val c = scala.collection.mutable.ArrayBuffer[Int]() c += 1 c += 2 c += (3,4,5) c ++= Array(6,7,8) c.insert(0,0) c.remove(1) c.remove(0,3) c.trimEnd(2) // for(i <- 0 until c.length) { // println(c(i)) // } // for(ele <- c) { // println(ele) // } for(i <- (0 until c.length).reverse) { println(c(i)) } // println(c.toArray.mkString) }
List
nil 就是 一个空的集合的意思

package com.imooc.scala.course05 object ListApp extends App{ // val l = List(1,2,3,4,5) // // // val l5 = scala.collection.mutable.ListBuffer[Int]()//可变list // l5 += 2 // l5 += (3,4,5) // l5 ++= List(6,7,8,9) // // // l5 -= 2 // l5 -= 3 // l5 -= (1, 4) // l5 --= List(5,6,7,8) // // println(l5) // // // l5.isEmpty // l5.head // l5.tail def sum(nums:Int*):Int = { if(nums.length == 0) { 0 } else { nums.head + sum(nums.tail:_*) // _* 类型自动转换 } } // val set = scala.collection.mutable.Set[Int]() // set += 1 // set += (1,1) println(sum()) println(sum(1,2,3,4)) }
head 就是 第一个, 而 tail 就是 除了 第一个数据的 之后的所有数据
set
无序,不可重复的 list ,用法与 list 类似 // val set = scala.collection.mutable.Set[Int]() //可变set // set += 1 // set += (1,1)
map


package com.imooc.scala.course05 import scala.collection.mutable object MapApp extends App{ val a = Map("PK" -> 18, "zhangsan" -> 30) val b = Map("PK" -> 18, "zhangsan" -> 30) // val c = mutable.HashMap[String,Int]() // b.getOrElse("PK", 9) // for((key,value) <- b) { // println(key + " : " + value ) // } // for(key <- b.keySet) { // println(key + " : " + b.getOrElse(key, 9)) // } // for(value <- b.values) { // println(value) // } for((key,_) <- b) { println(key + " : " + b.getOrElse(key, 9) ) } }
Option , Some, None
object OptionApp extends App { val m = Map(1 -> 2) // println(m(1)) // println(m(2)) // println(m.get(1).get) println(m.getOrElse(2, "None")) } /** * case object None extends Option[Nothing] { def isEmpty = true def get = throw new NoSuchElementException("None.get") } final case class Some[+A](x: A) extends Option[A] { def isEmpty = false def get = x } */
Option 是一个抽象类 , 实现类是 Some ,None
Some 代表存在, None 代表空
Tuple // 元组:(.......) object TupleApp extends App{ val a = (1,2,3,4,5) for(i <- 0 until(a.productArity)) { println(a.productElement(i)) } //下标从 1 开始,不是 0 val hostPort = ("localhost",8080) hostPort._1 hostPort._2 }
模式匹配
即 match case
类似 java 的 switch case 用法,但是比JAVA的强大很多 模式匹配 Java: 对一个值进行条件判断,返回针对不同的条件进行不同的处理 变量 match { case value1 => 代码1 case value2 => 代码2 ..... case _ => 代码N }
基本模式匹配 def grade(grade : String): Unit = { grade match{ case "A" => println("99。。。") case "B" => println("89。。。") case _ => println("00。。。") } }
条件匹配 def grade(grade : String): Unit = { grade match{ case "A" => println("99。。。") case "B" => println("89。。。") //条件匹配, 双重过滤 case _ if(grade=="C") => println("cc。。。") case _ => println("00。。。") } }
Array 模式匹配 def greeting(array:Array[String]): Unit = { array match { case Array("zhangsan") => println("Hi:zhangsan") //数组必须是 zhangsan case Array(x,y) => println("Hi:" + x + " , " + y) // 数组可以有任意的2个 case Array("zhangsan", _*) => println("Hi:zhangsan and other friends...")//多个内容, case _ => println("Hi: everybody...") } }
List 模式匹配 def greeting(list:List[String]): Unit = { list match { case "zhangsan"::Nil => println("Hi:zhangsan") //只有 zhangsan case x::y::Nil => println("Hi:" + x + " , " + y) //只有2个 任意元素 case "zhangsan"::tail => println("Hi: zhangsan and other friends...") // 多个 case _ => println("Hi:everybody....") } }
类型匹配 def matchType(obj:Any): Unit = { obj match { case x:Int => println("Int") case x:String => println("String") case m:Map[_,_] => m.foreach(println) // map , key value 任意 case _ => println("other type") } }
异常处理 //IO val file = "test.txt" try{ // open file // use file val i = 10/0 println(i) } catch { case e:ArithmeticException => println("除数不能为0..") case e:Exception => println(e.getMessage) } finally { // 释放资源,一定能执行: close file }
case class 模式匹配 def caseclassMatch(person:Person): Unit = { person match { case CTO(name,floor) => println("CTO name is: " + name + " , floor is: " + floor) case Employee(name,floor) => println("Employee name is: " + name + " , floor is: " + floor) case _ => println("other") } } class Person case class CTO(name:String, floor:String) extends Person case class Employee(name:String, floor:String) extends Person case class Other(name:String) extends Person caseclassMatch(CTO("PK", "22")) caseclassMatch(Employee("zhangsan", "2")) caseclassMatch(Other("other"))
Some None 模式匹配 val grades = Map("PK"->"A", "zhangsan"-> "C") def getGrade(name:String): Unit = { val grade = grades.get(name) grade match { case Some(grade) => println(name + ": your grade is :" + grade) case None => println("Sorry....") } }
高级函数
字符串高级操作 object StringApp extends App { val s = "Hello:" val name = "PK" // println(s + name) println(s"Hello:$name") val team = "AC Milan" // 插值 println(s"Hello:$name, Welcome to $team") val b = """ |这是一个多行字符串 |hello |world |PK """.stripMargin println(b) }
查值,就是 s + “ xx $属性名 ” , 必须是 s 开头的, 属性名 必须带上 $
匿名函数

匿名参数传递给 对应函数

匿名函数传递给 add 函数 , 或者 匿名函数传递给变量都是可以的
currying 函数 // 将原来接收两个参数的一个函数,转换成2个 def sum(a:Int, b:Int) = a+b println(sum(2,3)) // 改成 currying 函数 def sum2(a:Int)(b:Int) = a + b println(sum2(2)(3))
即将参数给 拆开
高阶函数


package com.imooc.scala.course07 /** * 匿名函数: 函数是可以命名的,也可以不命名 * (参数名:参数类型...) => 函数体 */ object FunctionApp extends App { // def sayHello(name:String): Unit = { // println("Hi: " + name) // } // // sayHello("PK") // // 将原来接收两个参数的一个函数,转换成2个 // def sum(a:Int, b:Int) = a+b // println(sum(2,3)) // // def sum2(a:Int)(b:Int) = a + b // println(sum2(2)(3)) val l = List(1, 2, 3, 4, 5, 6, 7, 8) //map: 逐个去操作集合中的每个元素 // l.map((x: Int) => x + 1) // l.map((x) => x * 2) // l.map(x => x * 2) // l.map(_ * 2).foreach(println) // l.map(_ * 2).filter(_ > 8).foreach(println) // 1+2 3+3 6+4 10+5 // l.reduce(_+_) // 即 求和 sum l.reduceLeft(_-_) l.reduceRight(_-_) l.fold(0)(_-_) println( l.fold(100)(_ + _)) // 从 100 开始 以此 求和 val f = List(List(1,2),List(3,4),List(5,6)) f.flatten // // 压扁 合成一个 List // flatMap f.map(_.map(_*2)) //每个元素 乘以2 f.flatMap(_.map(_*2)) // 并合成一个 List, 每个元素 乘以2 , val txt = scala.io.Source.fromFile("/Users/rocky/imooc/hello.txt").mkString // println(txt) val txts = List(txt) // 如何使用scala来完成wordcount统计 // 链式编程:Hibernate、Spark txts.flatMap(_.split(",")).map(x => (x,1)) //... .foreach(println) }
偏函数 /** * 偏函数:被包在花括号内没有match的一组case语句 */ object PartitalFunctionApp extends App { val names = Array("Akiho Yoshizawa", "YuiHatano", "Aoi Sola") val name = names(Random.nextInt(names.length)) name match { case "Akiho Yoshizawa" => println("吉老师...") case "YuiHatano" => println("波老师....") case _ => println("真不知道你们在说什么....") } // A 输入参数类型 B 输出参数类型 // A 输入参数类型 第一个参数, B 输出参数类型 第二个参数, def sayChinese:PartialFunction[String,String] = { case "Akiho Yoshizawa" => "吉老师..." case "YuiHatano" => "波老师...." case _ => "真不知道你们在说什么...." } println(sayChinese("Akiho Yoshizawa")) }
隐式转换
即类似 java 的 动态代理 AOP
需求:为一个已存在的类添加一个新的方法
Java:动态代理
Scala:隐式转换
双刃剑
Spark/Hive/MR.... 调优 import java.io.File //import ImplicitAspect._ object ImplicitApp { // 定义隐式转换函数即可 // implicit def man2superman(man:Man):Superman = new Superman(man.name) // val man = new Man("PK") // man.fly() // implicit def file2RichFile(file: File): RichFile = new RichFile(file) // val file = new File("/Users/rocky/imooc/hello.txt") // val txt = file.read() // println(txt) } //class Man(val name: String) { // def eat(): Unit = { // println(s"man[ $name ] eat ..... ") // } //} // //class Superman(val name: String) { // def fly(): Unit = { // println(s"superman[ $name ] fly ..... ") // } //} class RichFile(val file: File) { def read() = { scala.io.Source.fromFile(file.getPath).mkString } }
隐式参数
object ImplicatParam extends App { def testParam(implicit name:String): Unit ={ println(name) } // testParam("aa") // implicit val name2 ="bb" // testParam// 不会报错,默认使用 name2 // implicit val s1="s1" // implicit val s2="s2" // testParam // 多个 会报错,不知道用 s1 还是 s2 }
隐式类 object ImplicitClassApp extends App { implicit class Calcuotor(x:Int){ def add(a:Int) = a+x } println(1.add(3)) // 可以使用调用 Calcuotor 方法 }
scala 操作外部数据
读取文件及网络数据 import scala.io.Source object FileApp { def main(args: Array[String]): Unit = { val file = Source.fromFile("/Users/rocky/imooc/hello.txt")(scala.io.Codec.ISO8859) def readLine(): Unit ={ for(line <- file.getLines()){ println(line) } } //readLine() def readChar(): Unit ={ for(ele <- file) { println(ele) } } // readChar() def readNet(): Unit ={ val file = Source.fromURL("http://www.baidu.com") for(line <- file.getLines()){ println(line) } } readNet() } }
读取mysql package org.train.scala.c9 import java.sql.{Connection, DriverManager} object MySQLApp { def main(args: Array[String]): Unit = { val url = "jdbc:mysql://localhost:3306/mysql" val username = "root" val password = "123456" var connection:Connection = null try{ // make the connection classOf[com.mysql.jdbc.Driver] connection = DriverManager.getConnection(url, username, password) // create the statement, and run the select query val statement = connection.createStatement() val resultSet = statement.executeQuery("select host,user from user") while(resultSet.next()){ val host = resultSet.getString("host") val user = resultSet.getString("user") println(s"$host, $user") } } catch { case e:Exception => e.printStackTrace() } finally { // free if(connection == null) { connection.close() } } } }
与java 写法一样的
操作xml <fix major="4" minor="2"> <header> <field name="BeginString" required="Y">FIX4.2</field> <field name="MsgType" required="Y">Test</field> </header> <trailer> <field name="Signature" required="N"/> <field name="CheckSum" required="Y"/> </trailer> <messages> <message name="Logon" msgtype="A" msgcat="admin"> <field name="ResetSeqNumFlag" required="N"/> <field name="MaxMessageSize" required="N"/> <group name="NoMsgTypes" required="N"> <field name="RefMsgType" required="N"/> <field name="MsgDirection" required="N"/> </group> </message> <message name="ResendRequest" msgtype="2" msgcat="admin"> <field name="BeginSeqNo" required="Y"/> <field name="EndSeqNo" required="Y"/> </message> </messages> <fields> <field number="1" name="TradingEntityId" type="STRING"/> <field number="4" name="AdvSide" type="STRING"> <value enum="X" description="CROSS"/> <value enum="T" description="TRADE"/> </field> <field number="5" name="AdvTransType" type="STRING"> <value enum="N" description="NEW"/> </field> </fields> </fix> package org.train.scala.c9 import java.io.{FileInputStream, InputStreamReader} import scala.xml.XML object XMLApp { def main(args: Array[String]): Unit = { // loadXML() // readXMLAttr() updateXML() } def updateXML(): Unit ={ val xml = XML.load(this.getClass.getClassLoader.getResource("books.xml")) // println(xml) val bookMap = scala.collection.mutable.HashMap[String,String]() (xml \ "book").map(x => { val id = (x \ "@id").toString() val name = (x \ "name").text.toString bookMap(id) = name }) // for((key,value) <- bookMap) { // println(s"$key : $value") // } val newXml = <bookshelf>{bookMap.map(updateXmlFile)}</bookshelf> // println(newXml) XML.save("newBooks.xml", newXml) } def updateXmlFile(ele:(String,String)) = { val (id, oldName) = ele <book id={id + "-new"}> <name>{oldName + " Programming"}</name> </book> } def readXMLAttr(): Unit = { val xml = XML.load(this.getClass.getClassLoader.getResource("pk.xml")) // println(xml) // header/field // val headerField = xml \ "header" \ "field" // println(headerField) // all field // val fields = xml \\ "field" // for (field <- fields) { // println(field) // } // header/field/name // val fieldAttributes = (xml \ "header" \ "field").map(_ \ "@name") // val fieldAttributes = (xml \ "header" \ "field" \\ "@name") // for (fieldAttribute <- fieldAttributes) { // println(fieldAttribute) // } //name="Logon" message // val filters = (xml \\ "message") // .filter(_.attribute("name").exists(_.text.equals("Logon"))) // val filters = (xml \\ "message") // .filter(x => ((x \ "@name").text).equals("Logon")) // for (filter <- filters) { // println(filter) // } // header/field content (xml \ "header" \ "field") .map(x => (x \ "@name", x.text, x \ "@required")) .foreach(println) } def loadXML(): Unit = { // val xml = XML.load(this.getClass.getClassLoader.getResource("test.xml")) // println(xml) // val xml = XML.load(new FileInputStream("/Users/rocky/source/scala-train/src/main/resources/test.xml")) // println(xml) val xml = XML.load( new InputStreamReader( new FileInputStream("/Users/rocky/source/scala-train/src/main/resources/test.xml") ) ) println(xml) } }
scala 结合spring boot
参考 https://gitee.com/odilil/boot-scala?_from=gitee_search
bean 注入 还可以: @Autowired val metaTableRepository : MetaTableRepository = null // 不能使用 _ 下划线 占位符来标识



科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

热门排行