object PrintDemo {
def main(args: Array[String]): Unit = {
val name:String = "tom"
val age:Int = 10
val heigh:Double = 175.5
// 1. 字符串的打印方式: 1. println 2. printf
println("name=" +name +",age=" +age +",heigh=" +heigh)
printf("name=%s, age=%d, heigh=%.2f\n",name,age,heigh)
//2. mkString:将集合元素转化为字符串
val a= Array("apple","banana","cherry")
// 添加前后缀
a.mkString("[", "-", "]")
// 3. 将嵌套数组转化为字符串
val b= Array(Array("a","b"), Array("c","d"))
a.flatten.mkString(",")
// 4. 对于大量转义字符及换行的字符串可以使用三个双引,使用“|”进行对其。
val sql2 =
s"""
|--曝光 // 左对齐
|load parquet.`${str2}` as t;
|select * from t as t1;
""".stripMargin
// 5. 访问、截取字符串,分隔字符
val s1 = "World"
val s2 = s1.substring(0,2)
val s3 = s1.split("l")
// 6. 处理字符串中的字符(map,filter,flatmap,for,foreach)
val upper1 = s1.map(i=>i.toUpper)
val upper2 = s1.map(_.toUpper)
val filter = s1.filter(i=>i !='o')
s1.foreach(println)
for (i <- s1 if i != 'l') {
println("i = "+i)
}
// 7. 字符串中的查找模式
val pattern = "[0-9]+".r
val address = "101 main street 123"
val match1 = pattern.findFirstIn(address)
val match2 = pattern.findAllIn(address)
println(match1,match2)
// 8.字符串中的替换模式
val address1 = address.replaceAll("[0-9]","x")
// 9. 抽取String中模式匹配的部分
val pattern1 = "([0-9]+) ([A-Za-z]+)".r
val pattern1(count,fruit) = "100 bananas"
println(count,fruit)
}
}
_* 通配符,不定长参数
:_* 作为一个整体,告诉编译器你希望将某个参数当作参数序列处理!例如val s = sum(1 to 5:_*) 就是将1 to 5当作参数序列处理
val age = 26 // 定义的是不可变的
var i = 10 // 定义可变变量
i += 1
val r1 : Int = 10 / 3 // 3 [不会进行四舍五入]
val r2 : Double = 10 / 3 // a.先得到 3; b. 3再转成3.0
val n1 = 20
val n2 = 40
val max = if (n1 > n2) n1 else n2
Scala的集合有三大类:序列Seq、集合Set、映射Map,所有的集合都扩展自Iterable特质。
// scala.collection.immutable
// 1. 定长数组:array
val array = new Array[Int](5)
val x= (arr.max,arr.min,array.length) // 数组最值、长度
array(0) //访问|更改数组
for (elem <- array) { println(elem) } // 遍历数组
val a= Array(1,20,90) //直接初始化
val b=Array(12,34,86)
val c= b++a // 合并数组 ++ ,若不同类型以左边为准,同union
val d= a++:b //合并数组,并将右边的类型作为最终结果返回 ++:
// diff 去交集 intersect 取交集, +: 1+:array(2,3)在数组前面加一个元素
// 多维数组 Array.ofDim[Int](n1,n2), n1代表多个一维数组, n2代表每一个一维数组中有几个元素
val array = Array.ofDim[Int](3,4)
println(array(1)(1)) // 访问元素
// 2. 不可变list,必须初始化,列表有头部和尾部的概念,分别使用head和tail获取
val anyList = List[Any](10,20,"jack")
val value = anyList(2) // 访问, 使用小括号和索引, 索引从0开始
val list1 = List[Any]("a","b","c")。// 追加元素
val listAdd = list1 :+ "后面"
val addList = "前面" +:list1
val list3 = List[Any]("A","B","C")
val listAddMany = 1::2::3::list3::list1 //元素排列的顺序, 就是新对象中的顺序
val list4 = List[Any]("AA","BB","CC")
val listAddList = 4::5::6::list4:::list1 //元素排列的顺序, 就是新对象中的顺序
// 3. 元组, 可以理解为一个容器,可以存放各种相同或不同类型的数据,访问Tuple的元素的方式是 tuple._1 , tuple._2,tuple._3 ......
val myTuple = (1, 2, "hello") // 创建
val a= new Tuple("1","hello")
println(myTuple.productElement(2)) //访问: 使用productElement(index), 索引从0开始
val iterator = myTuple.productIterator // 访问: 迭代器
iterator.foreach(println)
val iterator =myTuple.productIterator
// 4. 不可变map ,循环遍历映射: for((k,v) <- 映射),keys,values ,添加简直对,1.赋值添加 2. 使用+=
import scala.collection.mutable
val map1 = Map("Alice" -> 10, "Bob" -> 20, "welldo" -> "27岁") // 创建方式1
val map2 = Map(("Alice",10), ("Bob", 20), ("welldo" , "27岁")) //创建方式2,使用元祖
if (map2.contains("aa")) {
println("aa存在:" + map2("aa"))
}else{
println("aa不存在")
}
println(map2.getOrElse("aa", "this key is not exist")) //如果key存在,返回key对应的值。 如果key不存在,返回默认值。
// 数组之间的相互转换
val m1 = Map(3 -> "geeks", 4 -> "for", 2 -> "cs")
val result = m1.toList
// 1. 变长数组
import scala.collection.mutable.ArrayBuffer
val arr = ArrayBuffer[Any](3, 2, 5)
arr.append(4,6,8) // 增加元素
arr(0) = "白居易" // 更改元素
arr.remove(0) // 删除元素
// 1-2. 变长 / 定长 数组的转换 :arr1.toBuffer //定长数组 转 可变数组 (返回新的对象, 原对象不变), arr2.toArray //可变数组 转 定长数组 (返回新的对象, 原对象不变)
val arr = ArrayBuffer[Any](3, 2, 5)
val array = arr.toArray //转换
val buffer = array.toBuffer //转换
// 2. 可变list, ListBuffer是可变的list集合,可以添加,删除元素, ListBuffer属于序列
import scala.collection.mutable.ListBuffer
val lb1 = ListBuffer[Int](1, 2, 3)
// 3. 队列
import scala.collection.mutable
val queue = new mutable.Queue[Any]
queue += 1 . // 添加元素
queue ++= List("a","b") // 把List中的元素拿出来, 一个一个添加, 使用 ++=
val first = queue.dequeue() . 出队列, 从头部取出数据, queue本身会发生变化
// 4. 可变Map
val map3 = mutable.Map[String,Any]("a" -> 10, "b" -> 20, "c" -> 30)
map3("a") = "update" //修改
map3("A") = "add" //添加
val map4 = mutable.Map[String,Any]("a" -> 10, "b" -> 20, "c" -> 30)
map4 += ("e" -> 50, "f" ->60) . // 添加
map4 -= ("e", "f") // 删除
// 5. set += 添加新的元素,可变的支持增删操作
val ms = mutable.Set[Any]()
ms.add(1)
ms += ("a")
ms += 2.0
ms.remove(10) //删除不存在的,不会报错
ms.remove(1)
ms -= 2.0
// 1. map函数
l = List(1,2,3,4,5,6,7,8,9)
l.map(x=> x*2)
// 2. Filter 过滤函数
l.map(_*2).filter(_>8)
// 3. 聚合操作reduce,可以将一个列表中的数据合并为一个
val ar = List(1,2,3,4,5)
println( ar.reduce((x,y)=>x+y))
// 4. flod 相当于给reduceLeft 函数, 在最左边多加了一个 初始值
val ar1 = List(1, 2, 3, 4, 5)
println(ar1.fold(0)(_ + _))
// 5. flatmap映射:flat即压扁,压平,扁平化映射 将集合中的每个元素, 一个一个拿出来, 被f函数运算, 将运算后的结果,放到新的集合中返回,如果集合中还有集合, 那么也会拿出来(底层递归操作)
val names = List("Alice", "Bob", "Nick")
val upperName = names.flatMap(upper _)
// 6.获取Scala迭代器的前n个元素的最简单方法
recs.toList.sortWith(_._2>_._2).take(n)
list=Range(0,100) //左闭右开
for (i <- 1 to|until 5 reverse ) {
println("to: " + i) //左闭右闭
}
// 循环可以控制步长
for(i <- 1 to 3 if i != 2) {
println("守卫: "+ i )
}
for(i <- 1 to 3; j = 4 - i) {
println("引入变量: "+ j )
}
// 循环返回值,但是for循环的返回值必须要关键字 yield上场。如果没有yield,即返回为空
val res3 = for (i <- 1 to 10) yield {
if (i % 2 == 0) {
i
} else {
"不是偶数"
}
}
// 1. 可以用作模式匹配
val Pattern1="(s.*)".r
val Pattern2="(kp_max_.*)".r
val v1="spark"
val r= v1 match {
case Pattern(v1) | Pattern2(_) => "begin s*"
case "1" => "1"
case "3" => "3"
case _ => "default"
}
// 2. 范围匹配
for(x <- 1 to 10){
val r= x match {
case x if (x>=0 & x < 5)=> "1-5"
case x if (x>=5 & x<10) => "5-10"
case _ => "not found"
}
}
case 替代map(line=>{})的写法,不在使用._1._2 上一个父rdd的类型值可直接命名为变量使用
val zipped = data.rdd.map((s :Row) => s(0)).zip(tfidf)
val originData = zipped.map{
case (x1 :Int, x2 :Vector) => LabeledPoint(x1, x2)
}
// rdd.map(i=>{}) 与 rdd.map{ case ( 上一个rdd的类型值可直接命名为变量使用) =>{ }} 等效
object ScalaImplicit{
// 隐式参数,隐式参数列表必须放在方法的参数列表后面
implict val default :Int =50
def sum(s:Int)(implicit b:Int,c:Int){
a+b+c
}
val res=sum(10) // 其他两个参数就会默认使用类中的成员变量用implicit修饰的default的值。
隐式类 所带的构造参数有且只有一个,并且构造器中的参数是转换之前的对象
object ImplicitUnils{
// 隐式类
implicit class StringImprovement(val s :Sting){
def increment=s.map(x => (x+1).toChar)
}
// 隐式类
implicit class IntImprovement(val a:Int){
def square =a* a
}
// 隐式类
implicit class Ximalaya(val x: Test){
def getXName=x.getName
}
}
object Main extendd App {
import ImplicitUnils._
println("hello".increment)
print(2.square)
}
编译器在hello对象调用increment时发现对象上并没有increment方法,此时编译器就会在作用域范围内搜索隐式实体,发现有符合隐式类可以用来转换成有带有increment方法的Stringimprovement类
提示:Map[Char, Int]()
import scala.collection.mutable.ArrayBuffer
object comprehensiveExercise2 {
def main(args: Array[String]): Unit = {
val sentence = "abbcccddddeeeee"
//不可变map实现
var map = Map[Char, Int]()
val map2 = sentence.foldLeft(map)(count _)
println(map2)
//可变map实现
val map3 = mutable.Map[Char, Int]()
sentence.foldLeft(map3)(mutableCount _)
println(map3)
}
//这里用的是不可变的map, 每次返回新的map, 效率相对较低
def count(map:Map[Char, Int], char: Char):Map[Char, Int]={
val newMap = map + (char -> (map.getOrElse(char,0) +1) )
newMap
}
//用可变map来实现
def mutableCount(map:mutable.Map[Char, Int], char: Char) :mutable.Map[Char, Int]={
map += (char -> (map.getOrElse(char,0) +1) )
}
}
两个集合的合并操作,合并后每个元素是一个 对偶元组
object Zip1 {
def main(args: Array[String]): Unit = {
//拉链的基本使用-合并
val list = List("no1", "no2", "no3")
val list2 = List("北京", "上海", "广州")
val list3 = list zip list2
println(list3)
//结果遍历, 由于是 对偶元祖,所以用 _1, _2 来取值
for (item <- list3) {
println("编号=" + item._1 + ", 名字=" + item._2)
}
}
}
通过iterator方法从集合获得一个迭代器,通过while和for对集合进行遍历,iterator 的构建实际是 AbstractIterator 的一个匿名子类.
```scala
object Iterator2 {
def main(args: Array[String]): Unit = {
val iterator = List(1, 2, 3, 4, 5).iterator // 获取到迭代器 [链表实现]
println("--------遍历方式1 -----------------")
while (iterator.hasNext) { // hasNext 方法可以判断是否有下一个
println(iterator.next()) // next 取出下一个值
}
//注意, while遍历完后, 指针已经到了最后,
//再遍历, 则为空
println("--------遍历方式2 for -----------------")
for(enum <- iterator) {
println(enum) //
}
}
}
def sum(n1: Int, n2: Int): Int = {
n1 + n2 //执行到最后一行作为返回值
}
def arithmeticOpt(n1:Int,n2:Int,opt:Char) = {
if (opt == '+') {
n1 + n2
}else if (opt == '-'){
n1 - n2
}else{
null
}
}
def sumWithNoReturn(n1:Int,n2:Int){
n1+n2
}
// 1. 函数没有参数列表的时候, 定义时, 也可以省略()
def test1() ={
println("这个方法没有形参, 调用时可以不带()")
}
// 2. 函数体中如果只有一行代码, 则可以省略大括号{}
def test16 = println("函数体中如果只有一行代码, 则可以省略大括号{}")
// 3. 函数的形参可以为多个
def test2(name:String,age:Int)={
}
// 4. 可变参数
def sum (args: Int*)={
println("参数个数为: "+args.length)
var res = 0
for (elem <- args) {
res += elem
}
println("求和结果为: "+res)
}
函数编程中,接受多个参数的函数, 都可以转化为接受单个参数的函数,这个转化过程就叫柯里化
object Demo1 {
def main(args: Array[String]): Unit = {
//编写一个函数,接收两个整数,可以返回两个数的乘积,要求:
//使用常规的方式完成
println(mul(10, 10))
//使用闭包的方式完成
println(mulCurry(10)(9))
//使用函数柯里化完成
println(mulCurry2(10)(8))
}
def mul(x: Int, y: Int): Int = x * y
def mulCurry(x: Int): Int => Int = (y: Int) => x * y
def mulCurry2(x: Int)(y: Int): Int = x * y
}
/**
* 辅助构造器, 必须在第一行调用主构造器
*/
class Person2() {
var name: String = _
var age: Int = _
//构造器1
def this(name : String) {
this() //直接调用主构造器
this.name = name
}
//构造器2
def this(age : Int) {
this("匿名") //间接调用主构造器,因为 这里调用构造器1, 构造器1中调用了主构造器!
this.age = age
}
def this(name : String, age : Int) {
this() //直接调用主构造器
this.name = name
this.age = age
}
}
//父类
class Base {
//三种属性
var n1: Int = 1
protected var n2: Int = 2
private var n3: Int = 3
//方法
def test100(): Unit = {
println("base 100")
}
protected def test200(): Unit = {
println("base 200")
}
}
}
//子类Sub继承了Base父类
class Sub extends Base {
//方法
def sayOk(): Unit = {
//这里子类中,可以访问到父类的 默认和protected的属性和方法
this.n1 = 20 // n1_$eq()
this.n2 = 40 //...
//this.n3 = 90
println("范围\t" + this.n1 +"\t"+ this.n2)
test100()
}
}
/**
* scala规定,重写一个非抽象方法需要用override修饰符,
* 如果想调用 父类中被重写的这个方法,使用super关键字去调用
*/
object OverrideDemo3 {
def main(args: Array[String]): Unit = {
val emp = new Emp
emp.printName()
}
}
//Person2类
class Person2 {
var name: String = "tom"
//父类方法
def printName()= {
println("父类 printName() " + name)
}
}
class Emp extends Person2 {
//想去重写Person-printName方法,必须显式的声明 override
override def printName()= {
println("子类 printName() " + name)
//如果希望调用父类的printName,则需要使用super.printName()
super.printName()
}
}
/**
* 练习1
* 编写computer类, 包含 cpu型号,内存大小,硬盘大小, 等属性, getDetails 方法用于返回这些信息
*
* 编写PC子类, 继承computer,添加特有属性: 品牌brand
* 编写notePad子类, 继承computer,添加特有属性: 颜色color
*
* 编写 exercise1, 在main方法中创建pc 和notePad对象, 给对象中所有属性(继承属性+特有属性)赋值,并使用getDetails 方法打印
*/
object exercise1 {
def main(args: Array[String]): Unit = {
val pc = new PC
pc.cpu = "core i7"
pc.memory = 8
pc.hardDisk = 256
pc.brand = "lenovo"
pc.getDetails()
}
}
class computer {
var cpu: String = _
var memory: Int = _
var hardDisk: Int = _
def getDetails ()={
printf("cpu:%s, memory:%d, hardDisk:%d",cpu,memory,hardDisk)
}
}
class PC extends computer {
var brand: String = _
override def getDetails ()={
printf("cpu:%s, memory:%d, hardDisk:%d, brand:%s",cpu,memory,hardDisk,brand)
}
}
class NotePad extends computer {
var color: String = _
}