/**
学习scala写递归函数
1.scala递归函数的返回值类型必须显示声明,不能用自动推断
2.写递归的技巧,掌握两个要素:要素①找出函数关系
要素②找出结束条件
3.scala递归函数的结束条件返回值必须要return关键字返回
*/
object Demo11 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
//--给定一个斐波那契数列
//--2 3 5 8 13 21
//--目标是写一个递归函数,判断数列第n项的数字是多少
//-一函数关系:f(n)=f(n-1)+f(n-2)
//-–结束条件:f()=2 f(1)=3
def f1(n:Int):Int={
if(n==0){return 2}
if(n==1){return 3}
else f1(n-1)+f1(n-2)
} //> f1: (n: Int)Int
f1(2) //> res0: Int = 5
//--2 3 4 9 16 81 .
//--编写递归函数f2(n) ,判断第n项的数字是多少
def f2(n:Int):Int={
if(n==0) return 2
if(n==1) return 3
else f2(n-2)*f2(n-2)
} //> f2: (n: Int)Int
f2(5) //> res1: Int = 81
// --2 3 4 9 8 27 16 81 ...
//--编写递归函数f3(n),判断第n项的数字是多少
def f3(n:Int):Int={
if(n==0) return 2
if(n==1) return 3
if(n%2==0) f3(n-2)*2
else f3(n-2)*3
} //> f3: (n: Int)Int
f3(8) //> res2: Int = 32
//10-1 循环输出
for(i<-0 to 9)println(10-i) //> 10
//| 9
//| 8
//| 7
//| 6
//| 5
//| 4
//| 3
//| 2
//| 1
//=========================================
//利用一个函数,n-1 遍历输出
//方式0
def f4(n:Int):Unit={
for(i<-0 to n-1)println(n-i)
} //> f4: (n: Int)Unit
f4(10) //> 10
//| 9
//| 8
//| 7
//| 6
//| 5
//| 4
//| 3
//| 2
//| 1
//方式1
for (i<-10 to 0 by -1) println(i) //> 10
//| 9
//| 8
//| 7
//| 6
//| 5
//| 4
//| 3
//| 2
//| 1
//| 0
//方式2
for( i<-0 to 10 reverse) println(i) //> 10
//| 9
//| 8
//| 7
//| 6
//| 5
//| 4
//| 3
//| 2
//| 1
//| 0
//===================================================
//扑克牌,确定抽出的一张是什么牌
//红桃A-K 1-13 黑桃A-K 14-26 梅花A-K 27-39 方块A-K 40-52 大王 53 小王 54
//生成一个数字---模拟,实际中只能确定剩余牌数
var a1=scala.util.Random.nextInt(100)
//> a1 : Int = 95
//模拟剩余和
var num=0 //> num : Int = 0
var i=1 //> i : Int = 1
while(i<55) {
num=num+i
i+=1
}
//实际中应该是是确定了这个总和,去求a1
println(num-a1) //> 1390
def f5(n:Int):Unit={
var k1=n/13
var k2=n%13
if(n==53) println("dawang")
if(n==54) println("xiaowang")
if(k1==1&&k2==0) println("red-K")
if(k1==0) println("red"+k2)
if(k1==2&&k2==0) println("black-K")
if(k1==1) println("black"+k2)
if(k1==3&&k2==0) println("mh-K")
if(k1==2) println("mh"+k2)
if(k1==4&&k2==0) println("fk-K")
if(k1==3) println("fk"+k2)
} //> f5: (n: Int)Unit
f5(a1)
///===========
//123456
//214365
//n为偶数
//将左右两个数替换 1 2 -----2 1
//方式1
var arr=Array(1,2,3,4,5,6,7,8,9,10) //> arr : Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val len=arr.length //> len : Int = 10
var ii=2 //> ii : Int = 2
var sum="" //> sum : String = ""
while(ii<=len){
sum+=(arr(ii-1).toString())+(arr(ii-2).toString())
ii+=2
}
println(sum) //> 21436587109
//方式2
var array=Array(1,2,3,4,5,6) //> array : Array[Int] = Array(1, 2, 3, 4, 5, 6)
def resv(arr:Array[Int])={
for(i<-0 until(arr.length-1, 2)){
val t=arr(i)
arr(i)=arr(i+1)
arr(i+1)=t
}
} //> resv: (arr: Array[Int])Unit
resv(array)
array //> res3: Array[Int] = Array(2, 1, 4, 3, 6, 5)
//编写函数计算x的n次方,其中n是整数,要考虑等n是0,正偶数,正奇数,负数这几种情况。
//比如当x=2时,此函数要算出2^4,2^3,2^0,2^(-1)对应的值
def mi(x:Double,n:Int):Double={
if(n==0) return 1
else if(n>0&&n%2==0){
mi(x,n/2)*mi(x,n/2)
}else if(n>0&&n%2==1){
mi(x,n-1)*x
}else{
1/mi(x,-n)
}
} //> mi: (x: Double, n: Int)Double
mi(2,3) //> res4: Double = 8.0
//
val m2=Map("book"->10,"gun"->100,"ipad"->1000)//> m2 : scala.collection.immutable.Map[String,Int] = Map(book -> 10, gun -> 1
//| 00, ipad -> 1000)
val a5=for((k,v)<-m2)yield{(k,v*0.9)}
//> a5 : scala.collection.immutable.Map[String,Double] = Map(book -> 9.0, gun
//| -> 90.0, ipad -> 900.0)
}
import scala.collection.mutable._
/**
知识点
1.scala支持懒值机制,通过lazy关键字来声明
2.懒值的特点是声明时并不是马上赋值,被调用时才会赋值
3.注意:lazy只能修饰常量(val),不能修饰变量(var)
4.scala的集合(collection)类型包含如下的类型:Array , List, set,Map, Tuple, I
5.immutable---定长的概念:一经声明,长度不能增加(不能修改)|
6.mutable----变长的概念:声明之后,可以追加(长度可变)
**/
object Demo02 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
val v1=100 //> v1 : Int = 100
lazy val v2=100 //> v2: => Int
println(v2) //> 100
//申明一个定长的数组 赋值
val a1=Array(1,2,3) //> a1 : Array[Int] = Array(1, 2, 3)
//--声明一个定长为3的数组,没有赋值
val a2=new Array(3) //> a2 : Array[Nothing] = Array(null, null, null)
//申明一个边长数组并赋值
val a3=scala.collection.mutable.ArrayBuffer(1,2,3,4)
//> a3 : scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)
val a4=ArrayBuffer(1,2,3,4) //> a4 : scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)
//通过下标操作数组
a1(0) //> res0: Int = 1
a1(0)=10
a1(0) //> res1: Int = 10
//变长数组追加数据
a3.append(5)
a3 //> res2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5)
//|
val a5=Array(1,2,3,4,5,6) //> a5 : Array[Int] = Array(1, 2, 3, 4, 5, 6)
//去除前三个元素,并返回一个新数组
val r1=a5.take(3) //> r1 : Array[Int] = Array(1, 2, 3)
val r2=a5.takeRight(2) //> r2 : Array[Int] = Array(5, 6)
//取出数组的头一个元素.有别于take(1)
val r3=a5.head //> r3 : Int = 1
val r4=a5.take(1) //> r4 : Array[Int] = Array(1)
//删除前n个元素,将剩余元素返回到新数组中
val r5=a5.drop(2) //> r5 : Array[Int] = Array(3, 4, 5, 6)
val r6=a5.dropRight(2) //> r6 : Array[Int] = Array(1, 2, 3, 4)
//取出末尾元素,有别于takeRight(1)
val r7=a5.last //> r7 : Int = 6
val r8=a5.takeRight(1) //> r8 : Array[Int] = Array(6)
//最大值
val r9=a5.max //> r9 : Int = 6
//最小值
val r10=a5.max //> r10 : Int = 6
//求和
val r11=a5.sum //> r11 : Int = 21
//a5数组的均值
//val r12=(a5.sum)/a5.length
val r12=(a5.sum).toDouble/a5.length //> r12 : Double = 3.5
val a6=Array(1,1,2,3,3,4) //> a6 : Array[Int] = Array(1, 1, 2, 3, 3, 4)
//去重
val r13=a6.distinct //> r13 : Array[Int] = Array(1, 2, 3, 4)
//
val a7=Array(1,2,3) //> a7 : Array[Int] = Array(1, 2, 3)
val a8=Array(3,4,5) //> a8 : Array[Int] = Array(3, 4, 5)
//取交集,并将结果返回新的数组
val r14=a7.intersect(a8) //> r14 : Array[Int] = Array(3)
//并集---返回新数组
val r15=a7.union(a8) //> r15 : Array[Int] = Array(1, 2, 3, 3, 4, 5)
//取差集
val r16=a7.diff(a8) //> r16 : Array[Int] = Array(1, 2)
val r17=a8.diff(a7) //> r17 : Array[Int] = Array(4, 5)
//val r18=a7.mkString
//将数组中的元素以字符串返回,并指定分隔符
val r18=a7.mkString(",") //> r18 : String = 1,2,3
//反转
val r19=a7.reverse //> r19 : Array[Int] = Array(3, 2, 1)
//根据指定的匿名函数过滤,并返回新数组
val r20=a7.filter{x=>x>1} //> r20 : Array[Int] = Array(2, 3)
val a9=Array(14,16,22,25,30,40,18) //> a9 : Array[Int] = Array(14, 16, 22, 25, 30, 40, 18)
//计算出a9中成年人的年龄之和
val r21=a9.filter{x=>x>=18}.sum //> r21 : Int = 135
//r21.sum
//要求统计未成年中最大的年龄
val r22=a9.filter{x=>x<18}.max //> r22 : Int = 16
//根据指定的匿名函数返回个数
val r23=a9.count{x=>x>20} //> r23 : Int = 4
val a10=Array(1,2,3,4) //> a10 : Array[Int] = Array(1, 2, 3, 4)
val a11=Array(3,4,5,6) //> a11 : Array[Int] = Array(3, 4, 5, 6)
//要求返回a10 a11中不重复的偶数个数
a10.union(a11).distinct.count{x => x%2==0} //> res3: Int = 3
//指定函数,是否存在
//返回true或false
val r25=a10.exists{x=>x>5} //> r25 : Boolean = false
//
val a12=Array("1310","1311","13111") //> a12 : Array[String] = Array(1310, 1311, 13111)
//判断a12中是否存在非法的手机号----4位是正常
val r26=a12.exists { x => x.length()!=4 } //> r26 : Boolean = true
val a13=Array(2,1,4,3,5) //> a13 : Array[Int] = Array(2, 1, 4, 3, 5)
//--按指定的匿名函数条件排序,并将结果返回到新数组中
//--升序
val r27=a13.sortBy{num=>num} //> r27 : Array[Int] = Array(1, 2, 3, 4, 5)
//降序
val r28=a13.sortBy { num => num }.reverse //> r28 : Array[Int] = Array(5, 4, 3, 2, 1)
//降序
val r29=a13.sortBy{num => -num} //> r29 : Array[Int] = Array(5, 4, 3, 2, 1)
val a14=Array("tom 23","rose 18","jim 35","jary 20")
//> a14 : Array[String] = Array(tom 23, rose 18, jim 35, jary 20)
//操作a14,按年龄升序
val r30=a14.sortBy { x => x.split(" ")(1).toInt }
//> r30 : Array[String] = Array(rose 18, jary 20, tom 23, jim 35)
//操作a14 取出年龄最大的两个人的数据
val r31=a14.sortBy { x => x.split(" ")(1).toInt }.takeRight(2)
//> r31 : Array[String] = Array(tom 23, jim 35)
val a15=Array(1,2,3,4) //> a15 : Array[Int] = Array(1, 2, 3, 4)
//--最重要的方法,映射方法,作用是将集合中的元素从一个形式转变到另一个形式
//--然后将结果返回到新的数组中
//改变元素形式, 元素个数不变
val r32=a15.map { num => num*2 } //> r32 : Array[Int] = Array(2, 4, 6, 8)
val r33=a15.map { num => num.toString() } //> r33 : Array[String] = Array(1, 2, 3, 4)
val a16=Array("tom M 23","rose F 29 20","jim M 35")
//> a16 : Array[String] = Array(tom M 23, rose F 29 20, jim M 35)
//操作a16 返回数组只含有姓名信息
val r34=a16.map { line => line.split(" ")(0) } //> r34 : Array[String] = Array(tom, rose, jim)
//操作a16 ,统计年龄最大的前两个人的年龄之和
val r35=a16.map { line => line.split(" ")(2).toInt }.sortBy { age => age }.takeRight(2).sum
//> r35 : Int = 64
val a17=Array(1,2,3,4) //> a17 : Array[Int] = Array(1, 2, 3, 4)
// --reduce规约方法,底层是一种迭代方法
// --①次迭代a=1 b=2 a+b=3
// --②次迭代 a=3 b=3 a+b=6
// --③次迭代 a=6 b=4 a+b=10
val r36=a17.reduce{(a,b)=>a+b} //> r36 : Int = 10
//计算1-6的阶乘
//val r37=(1 to 6).reduce{(a,b)=>a*b}
val r37=1 to 6 reduce{(a,b)=>a*b} //> r37 : Int = 720
}
/**
学习List
Array和List通用而且重要的方法
1.take
2.takeRight
3.drop
4.dropRight
5.head
6.last
7.max
8.min
9.sum
10.mkstring
11.intersect
12.union
13.diff
14.filter
15.sortBy
16.count
17.exists -
18.map
19.reduce
20.distinct
21.foreach
再重点掌握:1.filter .sortBy 3.map 4.reduce
*/
object Demo03 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
//申明一个定长list,并赋值
val l1=List(1,2,3,4) //> l1 : List[Int] = List(1, 2, 3, 4)
//申明一个定长list 指定长度
val l2=List[Int](3) //> l2 : List[Int] = List(3)
//申明变长list
val l3=scala.collection.mutable.ListBuffer(1,2,3,4)
//> l3 : scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4)
l3.foreach { x => println(x) } //> 1
//| 2
//| 3
//| 4
//基于某一个list 添加元素,返回一个新list
val l4=l1.::(5) //> l4 : List[Int] = List(5, 1, 2, 3, 4)
//-掌握类型间转换技巧
//--比如某一种集合类型没有指定的方法,可以尝试先转变为Array或List来处理
val l5=List(1,1,2,2,3) //> l5 : List[Int] = List(1, 1, 2, 2, 3)
l5.toArray.distinct.toList //> res0: List[Int] = List(1, 2, 3)
}
/**
学习set
*/
object Demo04 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
//--声明定长set
val s1=Set(1,1,2,3,3) //> s1 : scala.collection.immutable.Set[Int] = Set(1, 2, 3)
//申明变长set
val s2=scala.collection.mutable.Set(1,2,3,4) //> s2 : scala.collection.mutable.Set[Int] = Set(1, 2, 3, 4)
val s3=Set(1,2,3) //> s3 : scala.collection.immutable.Set[Int] = Set(1, 2, 3)
val s4=Set(3,4,5) //> s4 : scala.collection.immutable.Set[Int] = Set(3, 4, 5)
//取交集
s3.intersect(s4) //> res0: scala.collection.immutable.Set[Int] = Set(3)
s3&s4 //> res1: scala.collection.immutable.Set[Int] = Set(3)
//取并集
s3.union(s4) //> res2: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)
s3++s4 //> res3: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)
//取差集
s3.diff(s4) //> res4: scala.collection.immutable.Set[Int] = Set(1, 2)
s3&~s4 //> res5: scala.collection.immutable.Set[Int] = Set(1, 2)
}
/**
学习map
*/
object Demo05 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
//申明一个定长map
val m1=Map("tom"->23,"rose"->30) //> m1 : scala.collection.immutable.Map[String,Int] = Map(tom -> 23, rose -> 30
//| )
//申明变长map。可以追加
val m2=scala.collection.mutable.Map("tom"->23,"rose"->30)
//> m2 : scala.collection.mutable.Map[String,Int] = Map(rose -> 30, tom -> 23)
//|
//通过key取value
m1.apply("tom") //> res0: Int = 23
//可以省略apply
m1("tom") //> res1: Int = 23
//不存在会报错,用get方法返回none
//m1("tom1")
//通过get取值,返回一个option类型
// --option有两个子类:Some None
// --如果指定的key有value,就将value封装到Some里
//--如果不存在指定的key,则返回None
m1.get("tom") //> res2: Option[Int] = Some(23)
m1.get("tom1") //> res3: Option[Int] = None
//通过getOrElse获取some里的值
//返回是none,返回指定的默认值
m1.get("tom").getOrElse(0) //> res4: Int = 23
m1.get("tom1").getOrElse(0) //> res5: Int = 0
//变长map做追加
m2+=("jim"->35,"jary"->40) //> res6: Demo05.m2.type = Map(jary -> 40, jim -> 35, rose -> 30, tom -> 23)
//返回map中key的迭代器
m1.keys //> res7: Iterable[String] = Set(tom, rose)
//返回map中value的迭代器
m1.values //> res8: Iterable[Int] = MapLike(23, 30)
//掌握case匹配的使用方法
val r1=m1.filter{case(k,v)=>v>25} //> r1 : scala.collection.immutable.Map[String,Int] = Map(rose -> 30)
//操作m1,将每个人的年龄加10
val r2=m1.map{case(k,v)=>(k,v+10)} //> r2 : scala.collection.immutable.Map[String,Int] = Map(tom -> 33, rose -> 40
//| )
//--操作Map类型时,如果只针对Map的Value做映射
//--可以用mapvalues方法
val r3=m1.mapValues { x => x+10 } //> r3 : scala.collection.immutable.Map[String,Int] = Map(tom -> 33, rose -> 40
//| )
m1.foreach{x=>println(x)} //> (tom,23)
//| (rose,30)
m1.foreach{case(k,v)=>println(k)} //> tom
//| rose
val r4=m1.toArray //> r4 : Array[(String, Int)] = Array((tom,23), (rose,30))
val r5=m1.toList //> r5 : List[(String, Int)] = List((tom,23), (rose,30))
}
/**
学习Tuple(元组)类型。这种类型最常用,最灵活的数据类型
通过(()声明的数据,就是一个元组类型
*/
/**
学习Tuple(元组)类型。这种类型最常用,最灵活的数据类型
通过(()声明的数据,就是一个元组类型
*/
object Demo06 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
//申明一个包含四个元素的数组
val t1=(1,2,3,4) //> t1 : (Int, Int, Int, Int) = (1,2,3,4)
val t2=(1,"hello",Array(1,2,3,4),List(3,4)) //> t2 : (Int, String, Array[Int], List[Int]) = (1,hello,Array(1, 2, 3, 4),List
//| (3, 4))
//元组取值,通过._ 下标取值
t2._2 //> res0: String = hello
val t3=((1,2),Array(3,4,5),(6,7,8)) //> t3 : ((Int, Int), Array[Int], (Int, Int, Int)) = ((1,2),Array(3, 4, 5),(6,7
//| ,8))
//操作t3,取出7
t3._3._2 //> res1: Int = 7
//操作t3 取出数字5
t3._2(2) //> res2: Int = 5
val m1=Map("tom"->23,"rose"->30) //> m1 : scala.collection.immutable.Map[String,Int] = Map(tom -> 23, rose -> 30
//| )
//过滤m1,过滤出>25的数据。两种方式
m1.filter{case(k,v) => v>25} //> res3: scala.collection.immutable.Map[String,Int] = Map(rose -> 30)
m1.filter{x=>x._2>25} //> res4: scala.collection.immutable.Map[String,Int] = Map(rose -> 30)
//m1.map{case(k,v)=>if(v>25)println(k,v)}
//m1.mapValues { x => if(x>25)println(x) }
//for((k,v)<-m1)yield(k,v>25)
val l1=List(("b",3),("a",4),("c",1),("d",2)) //> l1 : List[(String, Int)] = List((b,3), (a,4), (c,1), (d,2))
//要求操作l1,根据字母升序排序
l1.sortBy{line => line._1} //> res5: List[(String, Int)] = List((a,4), (b,3), (c,1), (d,2))
l1.sortBy{line => -line._2} //> res6: List[(String, Int)] = List((a,4), (b,3), (d,2), (c,1))
l1.sortBy{case(x,y)=> -y} //> res7: List[(String, Int)] = List((a,4), (b,3), (d,2), (c,1))
val l2=List(("hello",1),("hello",1),("world",1),("hello",1))
//> l2 : List[(String, Int)] = List((hello,1), (hello,1), (world,1), (hello,1))
//|
//操作l2 返回新的lsit (hello,world)
l2.map{x=> x._1}.distinct //> res8: List[String] = List(hello, world)
l2.map{case(x,y)=> x}.distinct //> res9: List[String] = List(hello, world)
val l3=List(("tom","M",15000),("rose","F",16000),("jim","M",10000),("jary","M",12000))
//> l3 : List[(String, String, Int)] = List((tom,M,15000), (rose,F,16000), (ji
//| m,M,10000), (jary,M,12000))
//统计出男性薪资最高的前两名的薪资和
l3.filter{x=> x._2=="M"}.sortBy{x=> x._3}.takeRight(2).map{x=> x._3}.sum
//> res10: Int = 27000
val l4=List("hello world","hello hadoop","hello world")
//> l4 : List[String] = List(hello world, hello hadoop, hello world)
l4.map { x => x.split(" ") } //> res11: List[Array[String]] = List(Array(hello, world), Array(hello, hadoop)
//| , Array(hello, world))
//扁平化map,改变元素的形式,也改变元素个数
//一般的使用场景是读取文件后,将每一行中的数据拿到
l4.flatMap { x => x.split(" ")} //> res12: List[String] = List(hello, world, hello, hadoop, hello, world)
val l5=List("hello","hello","world","hello","worl")
//> l5 : List[String] = List(hello, hello, world, hello, worl)
//按照指定的匿名函数规则做分组
//--返回的是一个Map(key , value)
//--key是分组字段,value是相同数据组成的List
val r11=l5.groupBy { x => x } //> r11 : scala.collection.immutable.Map[String,List[String]] = Map(worl -> Li
//| st(worl), world -> List(world), hello -> List(hello, hello, hello))
val l6=List(("bj",1),("sh",2),("bj",3),("sh",4))//> l6 : List[(String, Int)] = List((bj,1), (sh,2), (bj,3), (sh,4))
//操作l6,按地址分组
val r12=l6.groupBy{x=> x._1} //> r12 : scala.collection.immutable.Map[String,List[(String, Int)]] = Map(bj
//| -> List((bj,1), (bj,3)), sh -> List((sh,2), (sh,4)))
val l7=List("hello world hadoop","hello world","hello hadoop")
//> l7 : List[String] = List(hello world hadoop, hello world, hello hadoop)
//--统计出l7中每个单词出现的频次
//--比如最后的结果:( hello,3 ) (world,2)(hadoop,2)
val r13=l7.flatMap { line => line.split(" ") }.groupBy { line => line }.toList.map{case(x,y)=>(x,y.count { x => x==x })}
//> r13 : List[(String, Int)] = List((hadoop,2), (world,2), (hello,3))
val r14=l7.flatMap { line => line.split(" ") }.groupBy { line => line }.mapValues { x => x.size }.toList
//> r14 : List[(String, Int)] = List((hadoop,2), (world,2), (hello,3))
val r15=l7.flatMap { _.split(" ") }.groupBy { line => line }.map{case(k,v)=> (k,v.size)}.toList
//> r15 : List[(String, Int)] = List((hadoop,2), (world,2), (hello,3))
//接着往下写,实现单词频次统计,不用使用size和length方法
val r16=l7.flatMap { x => x.split(" ") }.map { x => (x,1) }.groupBy{x=> x}.map{case(k,v)=> (k,v.count{v=> v==v})}
.map{case(k,v)=> (k._1,v)} //> r16 : scala.collection.immutable.Map[String,Int] = Map(hadoop -> 2, world
//| -> 2, hello -> 3)
l7.flatMap { x => x.split(" ") }.map { x => (x,1) }.groupBy{x=> x._1}.mapValues{x=>x.map{x=> x._2}.sum}.toList
//> res13: List[(String, Int)] = List((hadoop,2), (world,2), (hello,3))
//化简
l7.flatMap {_.split(" ") }.map { (_,1) }.groupBy{_._1}.mapValues{_.map{_._2}.sum}.toList
//> res14: List[(String, Int)] = List((hadoop,2), (world,2), (hello,3))
}
object Demo07 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
val p1=new Person("tom",23) //> p1 : Person = Person@7a79be86
//辅助构造
val p2=new Person("rose") //> p2 : Person = Person@34ce8af7
val p3=new Person(19) //> p3 : Person = Person@b684286
val p4=new Person //> p4 : Person = Person@880ec60
//p1.setName("tom")
//p1.setAge(18)
p1.getName() //> res0: String = tom
p1.getAge() //> res1: Int = 23
p2.getName() //> res2: String = rose
p3.getAge() //> res3: Int = 19
//p1.say()
//静态方法调用
Util.sleep() //> Zzz
//Person类的静态方法使用
Person.speak()
//
val item1=Item("tom",13) //> item1 : Item = Item(tom,13)
val item2=Item //> item2 : Item.type = Item
println(item1) //> Item(tom,13)
}
/**
*
* 1.scala的trait类比于java的Interface
* 2.trait(特质) 可以定义抽象方法
* 3.不同在于scala的特质还可以定义普通方法,这种设计机制的目的是让一个类实现多继承的效果(即把trait当做抽象类来处理)
*
*
*
*
*
*
*/
trait Dance {
def baLei():Int
def tiTa():String
//普通方法
def floor()={}
}
trait Drive {
def piaoyi():Unit
def stop():String
}
/**
* 知识点
* 1.通过case关键字来定义一个样列类
* 2.case class必须声明一个主构造器
* 3.当声明一个主构造器后,case class会默认声明一个空的辅助构造器
* 4.case class 不需要New就可以创建类的实例对象
* 5.case class 默认实现了tostring方法
* 6.case class默认混入了序列化特质
*
*
*
*
*/
case class Item(val name:String,val age:Int) {
}
/**
* 1.继承用extends
* 2.混入特质用with
* 3.scala是单继承,多混入
* 4.scala要求必须有而且仅有一个extends关键字
* 5.scala的序列化特质 Serializable
*
*/
//class LiuTeacher extends Teacher with Dance with Drive {
class LiuTeacher extends Dance with Drive with Serializable{
def makeNote(line: String): String = {
???
}
def teach(): Unit = {
???
}
// override def speak()={
//
// }
def baLei(): Int = {
???
}
def tiTa(): String = {
???
}
def piaoyi(): Unit = {
???
}
def stop(): String = {
???
}
}
/**
* 知识点
* 1.scala同java,通过class关键字来定义类
* 2.scala class可以定义成员变量和成员方法
* 3.scala class也是通过New来创建类的对象
* 4.默认的访问权限是public。此外可以通过private或者protected来修饰
* 5.scala class的方法支持重写和重载,定义同java
* 6.scala class有一个主构造器,可以有多个辅助构造器
* 7.scala class只有一个主构造器,在类上声明
*
*
* */
class Person(v1:String,v2:Int) {
//定义成员变量
//习惯定义成员变量时,附一个初始的变量值
private var name=v1
private var age=v2
//辅构造器--只接受姓名
//要求:辅助构造器中必须调用本类的其他构造器
def this(v1:String){
this(v1,0)
}
def setName(name:String)={
this.name=name
}
//两个构造器 一个是只接受年龄,另一个是空
//只接受年龄构造器
def this(v2:Int){
this("",v2)
}
//空构造器
def this(){
this("",0)
}
def getName()={
this.name
}
def setAge(age:Int)={
this.age=age
}
def getAge()={
this.age
}
def say()={
println("hello")
}
}
object Person{
//定义静态方法
def speak()={
}
}
/**
* 知识点
* 1.scala同java,通过extends来继承父类
* 2.scala同java,单继承
* 3.如果重写的方法是一个普通方法,需要加override
* 4.如果重写的方法是一个抽象方法,不需要加overridel
*
*
* */
class Student extends Person{
override def say()={
}
}
/**
* 知识点
* 1.scala同java,通对abstract来定义一个抽象类
* 2.s.cala的抽象类中可以定义抽象方法和普通方法
* 3.抽象方法没有方法体{}
*
*
* */
abstract class Teacher {
//抽象
def makeNote(line:String):String
//抽象
def teach():Unit
//普通方法
def speak()={}
}
/**
* 知识点
* 1.scala object单例对象类。
* 2.在scala object里定义的变量和方法都是静态的
* 3.scala object不能New
* 4.如果要写main方法,需要在单例对象类中来写
* 5.如果要为一个类(class)添加静态成员或方法,方式是:在class的同一个文件下,
* 创建一个同名的object类。此时,class和object产生了绑定关系
*
* class称为object的伴生类
* object成为class的伴生对象
*
*
*
*/
object Util {
def sleep()={
println("Zzz")
}
def main(args: Array[String]): Unit = {
val a1=Array(1,2,3,4)
a1.foreach { x => println(x) }
}
}
练习
1.对"Hello"和"World"进行拉链操作,会产生什么结果?
2.编写函数values(fun:(Int)=>Int,low:Int,high:Int),该函数输入和输出一个集合,对应给定区间内给定函娄入和输出。比如,
-5,-4,-3,-2,-1,0,1,2,3,4,5
values(x=>x*x,-5,5)应该产出一个对偶的集合(-5,25),(-4,16),(-3,9),...(3,9),(5,25)
3.如何用reduce得到数组中的最大元素?Array(1,2,3,4,5)
不用使用max
4.用to和reduceLeft实现阶乘函数比如算1~10的阶乘结果
5.编写函数largest(fun:(Int)=>Int,inputs:Seq[Int]),输出在给定输入序列中给定函数的最大值。举例来说,
largest(x=>10*x-x*x,1 to 10)应该返回251=>x=>10*x-x*x=9
2=>x=>10*x-x*x=16……
返回其中的最大值25
6.修改前一个函数,返回最大的输出对应的输入。举例来说,largestAt(fun:(Int)=>Int,inputs:Seq[Int])该返回5
7.编写一个函数,接收一个整数数组(Array[Int]),产出一个新的数组。
包含原数组中的所有正值,以原有顺序排列,之后的元素是所有零或负值,以原有顺序排列。
比如:Array(4,-2,0,-3,0,1,5),处理后的结果是:Array ( 4 ,1,5,0,0,-2,-3 )
//import scala.collection.mutable._
object Demo08 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
val s1="hello" //> s1 : String = hello
val s2="world" //> s2 : String = world
// --拉链操作,将对应项的数据放在一起
--进行拉链操作时,元素个数尽量一致
s1 zip s2 //> res0: scala.collection.immutable.IndexedSeq[(Char, Char)] = Vector((h,w), (e
//| ,o), (l,r), (l,l), (o,d))
val a1=Array(1,2,3,4) //> a1 : Array[Int] = Array(1, 2, 3, 4)
val a2=Array("a","b","c","d") //> a2 : Array[String] = Array(a, b, c, d)
a1 zip a2 //> res1: Array[(Int, String)] = Array((1,a), (2,b), (3,c), (4,d))
//可以在这里导包
import scala.collection.mutable._
def f1(f:(Int)=>Int,start:Int,end:Int)={
val result=ListBuffer[(Int,Int)]()
for(i<-start to end ){
result.append((i,f(i)))
}
result
} //> f1: (f: Int => Int, start: Int, end: Int)scala.collection.mutable.ListBuffer
//| [(Int, Int)]
f1(x=>x*x,-5,5) //> res2: scala.collection.mutable.ListBuffer[(Int, Int)] = ListBuffer((-5,25),
//| (-4,16), (-3,9), (-2,4), (-1,1), (0,0), (1,1), (2,4), (3,9), (4,16), (5,25))
//|
//--1次a=2 b=1
//result=2
// --2次a=2 b=5
//result=5
// --3次a=5 b=4
//result=5
val a3=Array(2,1,5,4,3) //> a3 : Array[Int] = Array(2, 1, 5, 4, 3)
a3.reduce{(a,b)=> if(a>b) a else b} //> res3: Int = 5
1 to 10 reduce{_*_} //> res4: Int = 3628800
def f2(f:(Int)=>Int,inputs:Seq[Int])={
val s=inputs.reduceRight{(a,b)=> if(f(a)>f(b)) a else b}
f(s)
} //> f2: (f: Int => Int, inputs: scala.collection.mutable.Seq[Int])Int
f2(x=>10*x-x*x,1 to 10 toArray) //> res5: Int = 25
def f3(f:(Int)=>Int,inputs:Seq[Int])={
val s=inputs.reduce{(a,b)=> if(f(a)>f(b)) a else b}
s
} //> f3: (f: Int => Int, inputs: scala.collection.mutable.Seq[Int])Int
f3(x=>10*x-x*x,1 to 10 toArray) //> res6: Int = 5
val a4=Array(1,2,0,0,5,-3,-2,4,-6) //> a4 : Array[Int] = Array(1, 2, 0, 0, 5, -3, -2, 4, -6)
def f4(arr:Array[Int])={
val arr1=for(i<-arr;if i>0)yield{i}
val arr2=for(i<-arr;if i==0)yield{i}
val arr3=for(i<-arr;if i<0)yield{i}
arr1.union(arr2).union(arr3)
} //> f4: (arr: Array[Int])Array[Int]
f4(a4) //> res7: Array[Int] = Array(1, 2, 5, 4, 0, 0, -3, -2, -6)
def f5(a:Int,b:Int):Option[Int]={
if(b!=0){
Some(a/b)
}else{
None
}
} //> f5: (a: Int, b: Int)Option[Int]
f5(5,1) //> res8: Option[Int] = Some(5)
f5(5,1).getOrElse(100) //> res9: Int = 5
}
思考
有一个文件,存储了40亿个整型数字(都不重复)要求找出哪些数字没有出现过,而且内存不能超过1GB
Int类型的范围将近43亿,所以文件中40亿,肯定是有些数字没有出现过。
如果用整型数组存40亿个数,内存占用=160亿B~15GB不满足要求,所有想办法解决。
不能使用大数据框架
题目说明
40亿个非负整数中找到没出现的数
题目要求
最多使用1GB内存
实现思路
32位无符号整数的范围是0~4294967295,现在有一个正好包含40亿个无符号整数的文件,所以在
整个范围中必然有没出现过的数。可以使用最多1GB的内存,怎么找到所有没出现过的数?
如果用整数数组来保存出现过的数,那么如果40亿个数都不同,存一个32位整数需要4B,所以最差
情况下需要40亿×4B=160亿字节,大约需要16GB的空间,这是不符合要求的。
解决方式
package cn.bit;
import java.util.BitSet;
import org.junit.Test;
public class TestDemo {
@Test
public void bitSetTest(){
//常见一个比特类型数组
// BitSet bs=new BitSet();
BitSet bs=new BitSet( Integer.MAX_VALUE);
//1010 0101
//--处理思路,将出现的数字对应的位进行设置,比如100出现过,则set(100)
//--最终,将出现的40亿数字用bitset存完之后,再次遍历,出现False对应的位数字
//--就是没有出现过的
bs.set(0);
bs.set(2);
bs.set(5);
bs.set(7);
for (int i = 0; i < bs.length(); i++) {
System.out.println(bs.get(i)==false?bs.get(i)+"###未出现"+i:"");
}
}
}