scala—基础I

scala解释器

  • scala解释器也被称为REPL,会快速编译scala代码为字节码文件,然后交给JVM类执行 
    read(取值)evaluate(求值)print(打印)loop(循环)
  • 计算表达式:在scala>输入scala代码,解释器会直接返回结果(进入scala>: win+R -> cmd -> scala.bat)
  • 如果没有指定变量来存放值,那么值默认的默认名称为res,并显示结果的数据类型
  • 内置变量 在后面可以继续使用res这个变量
  • 可以使用Tab进行自动补全

声明变量

  • val变量 
    可以声明val变量来存放表达式计算结果的值,但是之后就无法修改(类似java中的final修饰的常量)
  • var变量 
    var变量存放的值可以修改,在scala中建议大量的使用val
  • 无论是val还是var,都可以手动指定类型,如果不指定的话,scala会根据值进行类型推断

数据类型与操作符

  • 基本数据类型(Byte,Char,Int,Long,Float,Double,Boolean) 
    scala的数据类型统一都是类,指定进行基本数据类型和引用类型的转换操作,并且可以调用大量的函数(1.toString(),1.to(10)看不懂没关系,后面后的是机会让你看懂)
  • 加强版类型:很多加强类型给基本数据类型增加了上百种增强的功能或函数
  1. String类通过StringOps类增强了大量的函数"hello".intersect("world")
  2. 还提供了RichInt,RichDouble,RichChar等类型
  • 基本操作符 
    和Java的算术操作符基本没有区别但是scala没有++、–操作符

调用函数

除了方法外,scala还提供了函数 
数学函数:sqrt() pow() min() 
引入特定包是使用:import 包名._ 
例: import scala.math._( _:通配符,类似Java中的 *)

if

在scala中if表达式是有值的,就是if或else中最后一行语句的返回的值

  • 可以将if表达式赋予一个变量
 
 
  1. val aa = if(age>18) 1 else 0
  2. var aa=-1;
  3. if(age>18) aa=1 else aa=0
  • if表达式的类型推断if ,else子句的值得类型可能是不同的,scala回取两个类型的公共父类型
 
 
  1. if(age>18) "aa" else 0
  2. //此时if和else的值得类型分别是String和Int,则表达式的值得类型是Any

如果if后没有else,则默认else的值是Unit,也可以用()表示(类似Java中void或null)

 
 
  1. //意思相同的两种个写法
  2. val age =10 ; if (age>10) " adult"
  3. val age =10 ; if (age>10) " adult" else() //else的值是Unit,也可以用()表示

默认情况些,REPL只能解释一行语句,但if表达式要放在多行,可以使用{ } 
或者使用 :paste /ctrl+D(退出)方式

默认情况下scala不需要语句终结符,默认将每一行作为一个语句

一行放多条语句,使用;分隔,

 
 
  1. var a,b,c =0; if(a<10) { b=b+1;c=c+1}
  2. var a,b,c
  3. if(a<10){
  4. b=b+1
  5. c=c+1
  6. }

块表达式:{ } 中的值,其中包含多条语句,最后一条语句就是表达式的返回值

输入和输出

print 和println:和java一样 ,println打印时会加一个换行符 
printf:可以用于进行格式化

 
 
  1. printf("hi,my name is %s,i am %d years old.\n","Tom",30)

reaLine:允许我们从控制台读取用户输入的数据,类似java中的System.in和Scanner的作用

循环

scala拥有和java一样的while和do-while循环 
for循环和java有区别 
for(i<-表达式) //让变量i遍历右边的表达式的所有值 
在for循环的变量之前并没有val或var的指定,该变量的类型是集合的元素类型 
循环变量的作用于一直持续到循环结束 
until方法返回一个不包含上限的区间 
使用;分隔多个生成器

 
 
  1. for(i<- 1 to 3;j<- 1 to 3) print ((10*i+j)+" ") //使用;分隔多个生成器

在for循环中添加过滤条件if语句,称为守卫式

 
 
  1. for( i<- 1 to 3 ; j<- 1 to 3 if i!=j) print((10*i+j)+" ") // if前面没有;

在循环中使用变量

 
 
  1. for( i<- 1 to 3 ;from=4-i ;j<- from to 3) print((10*i+j)+" ")

推导式 
如果for循环的循环体以yield开始,该循环会构造出一个集合,每次迭代生成集合中的一个值

 
 
  1. for(i<- 1 to 10) yeild i%3

函数

在代码块中定义包含多行语句的函数体

 
 
  1. //单行函数
  2. def say(name:String)=print("hello"+ name)
  3. //多行函数
  4. def sum(n:Int):Int={
  5. var sum=0;
  6. for(i<- 1 to n) sum+=i
  7. sum //返回值
  8. }

在scala中定义函数时,需要定义函数的函数名,参数,函数体 
必须给出所有参数的类型,但是不一定给出函数的返回值的类型,只要右侧的函数体中不包含递归的语句,scala就可以执行推断出返回类型

  • 递归函数 
    函数体内递归调用函数自身
 
 
  1. //斐波那契数列
  2. def fab(n:Int):Int={
  3. if(n<=2) 1
  4. else fab(n-1)+fab(n-2)
  5. }
  • 默认参数 
    在调用某些函数是,不希望给出参数的具体值,希望采用参数自身的值,就是用定义时定义的默认参数的值 
    在调用函数时,可以不按照函数定义的顺序来传递参数,使用 参数名="参数值" 
    还可以混用,未命名的参数必须放在前面
  • 使用序列调用可变长参数
 
 
  1. val s = sum(1 to 5:_*) //:_*转换成参数序列
  2. //使用递归函数实现累加
  3. def sun(num:Int*):Int={ //num:Int*:任意多个num:Int
  4. if(num.length==0)0
  5. else nums.head+sum(name.tail:_*) //第一个数与除了第一个数字外的全部数相加
  6. }
  • 过程 
    定义函数时,函数体直接包裹在{ }中,没有使用=连接,则函数的返回值类型就是Unit,称之为过程
 
 
  1. def say(name:String)="hello"+name
  2. def say(name:String){print("hello"+name);"hello,"+name}
  3. def say(name:String):Unit="hello"+name
  • lazy 值 
    如果将一个变量声明为lazy,则只有在第一次使用该变量时,变量对应的表达式才会发生计算

数组

 
 
  1. //固定长度使用Array
  2. val aa = new Array[String](10)
  3. //不固定长度使用ArrayBuffer
  4. import scala.collection.mutbale.ArrayBuffer
  5. val ss= new ArrayBuffer[Int]
  6. //数组的基本操作
  7. ss+=1
  8. ss+=(1,2,3,4,5)
  9. ss++=Array(12,15,18)
  10. ss.trimEnd(3) //删除最后3个元素
  11. ss.insert(2,5) //从索引2的地方加入元素5
  12. ss.insert(2,5,6,7) //从索引2的地方加入元素5 6 7
  13. ss.remove(2) //删除索引为2的元素
  14. ss.remove(2,5) //从索引为2的地方开始删除5个元素

变长数组 -> 定长数组:toArray 
定长数组 -> 变长数组:toBuffer

  • 遍历数组
 
 
  1. for(i<-(0 until ss.length) print(ss(i)+" ") //正常遍历
  2. for(i<-(0 until ss.length).reverse print(ss(i)+" ") //逆序遍历
  3. for(i<-(0 until (ss.length,2) print(ss(i)+" ") //跳跃遍历,隔一个
  4. for(i<-(elem->ss) print(elem) //
  • 常用算法
 
 
  1. val aa =Array(3,5,9,7,8,6)
  2. val aa1= aa.sorted
  3. val aa2=aa.sortWith(_>_)
  4. val aa3=aa.sortWith(_<_)
  5. aa.mkString //将数组中的额每一个元素相连接
  6. aa.mkString("XXX") //使用XXX将数组中的额每一个元素相连接

映射

Scala中的映射就是键值对对的集合Map,默认情况下Scala中使用不可变的映射 
(如果想使用可变集合Map,必须导入scala.collection.mutable.Map)

 
 
  1. var aa=Map("Alice"->10,"Tom"->25) //可变集合
  2. val bb=scala.collection.mutbale.Map("Tony"->23,"Amy"->18) //不可变集合
  • 映射这种数据结构是将键映射到值得函数
  • 区别在于通常的函数计算值,而映射只是做查询 
    scala中集合分成三大类
  1. 序列(Seq)
  2. 集(Set)
  3. 映射(Map)
 
 
  1. //不可变
  2. val aa=Map ("tom"-> 20,"jack"->18, "sam"->25)
  3. //不可变
  4. val aa=Map (("tom"20),(“jack",18),("sam",25))
  5. //可变
  6. val bb=scala.collection.mutable.Map(("tom",20),("jack",18),("sam",25))
  7. //获取映射中的值
  8. val cc=aa("william") //如果映射不包含请求中的值,会抛异常
  9. val cc=aa("Tom")
  10. val cc= if (aa.contains("Tom")) aa("Tom") else 0 //检查映射中是否有某个指定的键
  11. val cc=aa.getOrElse("Tom",0) //如果包含相应的键,返回这个件所对应的值,否者返回0
  12. //映射.get(键)这样的调用返回一个option对象,要么是Some(键对应的值),要么是NONE
  • 修改Map的元素 
    可变Map集合
 
 
  1. //更新Map的元素
  2. bb("Amy")=50
  3. //增加多个元素
  4. bb+=("mike"->35)
  5. //移除元素
  6. bb-="mike"

修改不可变Map集合

 
 
  1. //添加元素,产生一个新的集合Map,原Map不变
  2. val cc =aa+("mike"->36)
  3. //移除元素,产生一个新的集合Map,原Map不变
  4. val cc =aa-"mike"

遍历Map操作

 
 
  1. //遍历map的entry
  2. for((key,value)<-aa) println(key+" "+value)
  3. //遍历map的key
  4. for(key<-aa.keySet) println(key)
  5. //遍历map的value
  6. for(value<-aa.values) println(value)
  7. //生成新的map,翻转key,value
  8. for((key,value)<-aa) yield(value,key)
  9. //SortedMap可以自动对map的key排序
  10. val cc=scala.collection.immutable.SortedMap("mike"->55,"Alice"->10,"Tom"->25)
  11. //LinkedHashMap可以记住插入entry的顺序
  12. val cc = new scala.collection.mutable.LinkedHashMap[String,Int]
  13. cc("Alice") =10
  14. cc("Tom") =25
  15. cc("mike") =55

javaMap和ScalaMap的隐式转换

 
 
  1. //Java map to scala map
  2. import scala.collection.JavaConversions.mapAsScalaMap
  3. val cc =new java.util.HashMap[String,Int]()
  4. cc.put("Tom",10)
  5. cc.put("Amy",20)
  6. cc.put("sam",30)
  7. val ss:scala.collection.mutable.Map[String,Int]=cc
  8. //scala map to java map
  9. import scala.collection.JavaConversions.mapAsJavaMap
  10. import java.awt.font.TextAttribute._
  11. val rr =Map(FAMILY->"aa",SIZE->2)
  12. val font=new java.awt.Font(rr)

元组

  • 元组是不同类型的值得聚集
  • 对偶是元组的最简单性形态 
    元组的索引是从1开始(不是0,不是0,不是0)
 
 
  1. val tuple=(2,5.5,"Tom")
  2. val second=tuple._2
  • 拉链操作 
    即zip操作,是Array类的方法,将两个Array合并成一个Array 
    Array(v1)和Array(v2),合并后的格式为Array((v1,v2)),合并后的元素类型为Tuple 
    (多的直接删掉)
 
 
  1. val aa=Array("a","b","c")
  2. val bb=Array(1,2,3)
  3. val cc=aa.zip(bb)
  4. for((aa,bb)<-cc)
  5. println(aa+" "+bb)

经典面试题

 
 
  1. 移除第一个负数后的所有负数
  2. //基本款
  3. var array=ArrayBuffer[Int]()
  4. array+=(1,2,3,4,5,-6,7,8,9,-1,-2,-3,-4)
  5. var arraylength=array.length
  6. var a=0
  7. var index=0
  8. while(index<arraylength){
  9. if(array(index)>=0){
  10. index+=1
  11. }else{
  12. if(a>0){array.remove(index);arraylength-=1}
  13. else{a+=1;index+=1}
  14. }
  15. }
  16. //优化款
  17. var array=ArrayBuffer[Int]()
  18. array+=(1,2,3,4,5,-6,7,8,9,-1,-2,-3,-4)
  19. var a=0
  20. val keepindex=for(i <- 0 until array.length if a<1 ||array(i)>=0) yield { if(array(i)<0) a+=1;i }
  21. for(i <- 0 until keepindex.length) {
  22. array(i)=array(keepindex(i))
  23. }
  24. array.trimEnd(array.length-keepindex.length)

高阶函数

把函数当做参数的函数 
filter 
完整版:arrary.filter(m=>m%2==0) //匿名参数m=>m%2==0 
简单版:arrary.filter(_%2==0) 
匿名函数: 
def test (m:Int)={m%2==0} => m =>{m%2==0} 
只有一个参数可以删除() 
数据类型可以删掉


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值