Scala学习教程笔记一之基础语法,条件控制,循环控制,函数,数组,集合
前言:Scala的安装教程:http://www.cnblogs.com/biehongli/p/8065679.html
1:Scala之基础语法学习笔记:
:声明val变量:可以使用val来声明变量,用来存放表达式的计算结果,但是常量声明后是无法改变它的值的,建议使用val来声明常量;
声明var变量:如果要声明可以改变的引用,可以使用var变量,声明的常量的值可以改变。
:指定类型:无论声明val变量还是声明var变量。都可以手动指定其类型,如果不指定,scala会自动根据值,进行类型的推断;
:声明多个变量:可以将多个变量放到一起进行声明,如val id,age :Int = ;val num1,num2=;
:基础数据类型:Byte,Char,Short,Int,Long,Float,Double,Boolean;记住,Scala没有包装数据类型;
:基本操作符:scala的算术操作符和Java的算术操作符没有什么区别,比如+ - * / %等等,以及其他操作符,& | >> << 等等,但是在scala中,这些操作符其实是数据类型的函数,比如1+1,可以写作1.+(1), to 10可以写作1.to()等等。
注意,在scala中没有提供++,--操作,我们只可以使用+=和-=操作符;
7:apply函数:在scala中apply函数是非常特殊的一种函数,在Scala的object中,可以声明apply函数。而使用"类名()"的形式,其实就是"类名.apply()"的一种缩写。通常使用这种方式来构造类的对象,而不是使用"new 类名()"的方式。
比如"hello world"(6)可以写成"hello world".apply(6);
2:Scala之条件控制学习笔记:
:if表达式的定义:在scala中,if表达式是有值的,就是if或者else中最后一行就是返回的值。
比如var age = ; if(age >) else ;
可以将if表达式赋予一个变量,比如var result = if(age >) else ;
:if表达式的类型推断,由于if表达式是有值的,而if和else子句的值类型可能是不同的。此时if表达式的值是什么类型的呢,scala可以自动进行推断,取两个类型的公共父类型。
比如:var age =;if(age > ) "成年人" else ;此时if和else的值分别是String和Int,则表达式的值就是Any,因为Any是String和Int的公共父类型。
:如果if后面没有跟else,则默认else的值是Unit,也可以用()表示,类似于Java中的void或者null。
:语句终结符:默认情况下,scala不需要语句终结符即;这个分号,默认每一行作为一个语句。
但是如果一行放多条语句,则必须使用语句终结符。
:块表达式。指的就是{}中的值,其中可以包含多条语句,最后一个语句的值就是块表达式的返回值。
:输出:print()和println(),其中print()打印的时候不会加换行,但是println()打印的时候会加一个换行符。
:输入:readLine:允许我们从控制台读取用户输入的数据,类似于Java中的System.in和Scanner的作用。
注意:readInt()输入是数值类型的。readDouble()是输入小数类型的。
3:Scala之循环控制学习笔记:
:while do循环,scala中的while do循环,基本和Java相同。
:for循环,比如:for(i <- 1 to 10) println(i);注意for循环的使用,多加揣摩和练习。
:跳出循环语句:scala中没有提供如Java中的跳出循环语句。但是可以使用boolean类型变量,return或者使用Breaks的break函数来替换使用。
比如:var flag : Boolean = false;for(i <- .to()) if(i%==){ flag = true; return flag;}
:scala的九九乘法表:
for(i <- .to(); j <- .to()){
if(j == ){
println(i + "*" + j + " = " + i*j);
}else{
print(i + "*" + j + " = " + i*j + " ");
} }
:scala的取偶数
for(i <- to if i % ==) println(i)
:for推导式,构造集合:
var a = for(i <- to ) yield i;
println(a)
4:Scala之函数学习笔记,面向对象和面向函数编程:
:函数的定义:需要定义函数的函数名,参数,函数体;Scala要求必须给出所有参数的类型,但是不一定给出函数返回值的类型,只要右侧的函数体中不包含递归的语句,Scala就可以根据自己右侧的表达式推断出返回类型。
比如:
def helloScala(name : String,age : Int): Unit ={
if(age > ){
println("恭喜您:" + name + "您已经:" + age+"岁了,您已经成年了");
}else{
println("恭喜您:" + name + "您已经:" + age+"岁了,您还是未成年哦");
}
}
helloScala("张三",);
:如果在函数体递归调用函数自身,则必须手动给出函数的返回值类型。
:默认参数,在Scala中,有时候在调用某些函数的时候,不希望给出参数的具体指,而希望使用参数自身默认的值,此时就在定义函数时使用默认参数。如果给出的参数不够,则会从左往右依次应用参数。
比如:
def hello(name :String="张三",age : Int=): Unit ={
println(name+ " " + age)
}
hello()
:带名参数:在调用函数的时候,也可以不按照函数定义的参数顺序来传递参数,而是使用带名参数的方式来传递;
还可以混合使用未命名参数和带名参数,但是未命名参数必须在带名参数前面。
比如:
def hello(name :String="张三",age : Int=): Unit ={
println(name+ " " + age)
}
hello(age=,name="李四")
hello("王五",age=)
:函数之变长参数:在Scala中,有时候我们需要将函数定义为参数个数可变的形式,则此时可以使用变长参数定义函数:
比如:
def add(nums : Int*): Int ={
var sum : Int= ;
for(num <- nums){
sum += num;
}
return sum;
}
var result = add(,,,);
println(result)
注意:如果想要将一个已有的序列直接调用变长参数,是不可以的。此时需要使用Scala特殊的语法将参数定义为序列,让Scala解释器能够识别:比如:var s = sum( to :_*)
比如:
def add(nums : Int*): Int ={
var sum : Int= ;
for(num <- nums){
sum += num;
}
return sum;
}
println(add( to :_*))
:函数之过程,定义函数的时候,如果函数体直接包裹在了花括号里面,而没有使用=连接,则函数的返回值就是Unit。这样的函数就被称之为过程。过程通常用于不需要返回值的函数。
注意:过程还有一种写法,就是将函数的返回值类型定义为Unit;
比如:
def hello(name : String) = "hello:" +name;
def hello(name : String) {println("hello:"+name);"hello:"+ name}
def hello(name : String) : Unit= "hello:" +name;
:Scala的异常:在scala中,异常处理和捕获机制与Java类似。
比如:
try{
throw new IllegalArgumentException("算数异常");
}catch{
case _:IllegalArgumentException => println("算术异常");
}finally {
println("最后一定执行这句话。")
}
8:高阶函数:
可以将函数A作为参数传递给函数B,此时这个函数B叫做高阶函数。此时函数A称为匿名函数,注意匿名函数的参数和类型。
textFile.filter((line : String) => line.contains("Spark")) #Scala可以自动推断类型,可以省略类型
textFile.filter((line) => line.contains("Spark")) #Scala参数只有一个,可以省略括号
textFile.filter(line => line.contains("Spark")) #_可以代表任意字符
textFile.filter(_.contains("Spark")
5:Scala之数组学习笔记:
:Array,在Scala中,Array也是长度可变的数组,此外,由于Scala与Java都是运行在Jvm中,双方可以互相调用,因此,Scala数组的底层实际上就是Java数组。
比如:数组初始化以后,长度就固定下来了,而且元素全部根据其类型初始化:
var arr = new Array[Int]()
var arr2 = new Array[String]()
可以直接使用Array()创建数组,元素类型自动推断:
var arr = Array("张三","李四");
println(arr())
:ArrayBuffer,在Scala中,如果需要类似于Java中ArrayList这种长度可变的集合类,则可以使用ArrayBuffer;
如果不想每次都使用全限定名,则可以预先导入ArrayBuffer类:
import scala.collection.mutable.ArrayBuffer
使用ArrayBuffer()方式可以创建一个空的ArrayBuffer:
var arr = ArrayBuffer[Int]();
println(arr.toBuffer)
使用+=操作符,可以添加一个元素或者多个元素:
arr += ;
println(arr.toBuffer)
arr += (,,,,);
println(arr.toBuffer)
使用++=操作符,可以添加其他集合中的所有元素:
arr ++= Array(,,,,,);
println(arr.toBuffer)
使用trimEnd()函数,可以从尾部截断指定个数的元素:
arr.trimEnd()
println(arr.toBuffer)
使用insert()函数可以在指定位置插入元素。但是这种操作效率很低,因为需要移动指定位置后的所有元素。
使用remove()函数可以移除指定位置的元素。
Array和ArrayBuffer可以互相进行转换:arr.toArray;arr.toBuffer
:遍历Array和ArrayBuffer
使用for循环和until遍历Array和ArrayBuffer:
使用until是RichInt提供的函数:
var arr = Array(,,,,,,,);
for(i <- .until(arr.length)){
print(arr(i) + " ")
}
跳跃遍历Array/ArrayBuffer
var arr = Array(,,,,,,,);
for(i <- .until(arr.length,)){
print(arr(i) + " ")
}
从尾部遍历Array/ArrayBuffer
var arr = Array(,,,,,,,);
for(i <- .until(arr.length).reverse){
print(arr(i) + " ")
}
使用增强for循环遍历Array/ArrayBuffer
var arr = Array(,,,,,,,);
for(i <- arr){
print(i + " ")
}
:数组的常用函数:
数组元素求和:
var arr = Array(,,,,,,,,);
println("求和:" + arr.sum)
获取数组的最大值和最小值:
println("最大值:"+ arr.max + " ,最小值:" + arr.min)
对数组进行排序:
quickSort(arr)
println("排序:"+ arr.toBuffer)
获取数组中所有的元素内容:
println("获取值:"+ arr.mkString(","))
toString函数
println(arr.toString)
:使用yield和函数式编程转换数组:
对数组Array进行转换,获取的还是Array:
var arr = Array(,,,,,,,,);
var result = for(i <- arr) yield i * i;
for(i <- result){
print(i + " ")
}
对数组ArrayBuffer进行转换,获取的还是ArrayBuffer:
var arr = ArrayBuffer[Int]();
arr += (,,,,,,,,);
var result = for(i <- arr) yield i * i;
for(i <- result){
print(i + " ")
}
结合if守卫,仅仅转换需要的元素:
var arr = ArrayBuffer[Int]();
arr += (,,,,,,,,);
var result = for(i <- arr if i % == ) yield i * i;
for(i <- result){
print(i + " ")
}
使用函数式编程转换数组,通常使用第一种方式:
var arr = ArrayBuffer[Int]();
arr += (,,,,,,,,);
var result = arr.filter(_ % == ).map( * _)
print(result.toBuffer + " ")
var result2 = arr.filter(_ % == ) map{ * _}
print(result2.toBuffer + " ")
6:Scala之集合中的Map,以及tuple的学习笔记:
:创建Map:
创建一个不可变的Map:
import scala.collection.immutable.Map
var map = Map("张三" ->,"李思思" -> );
println(map("张三"))
创建一个可变的Map:
import scala.collection.mutable.Map
var map = Map("张三" -> ,"李思思" -> );
println(map("张三"))
map("王五") = ;
println(map("王五"))
使用另外一种方式定义Map元素:
var map = Map(("张三",),("李四",),("王五",),("赵六",));
println(map.toBuffer)
创建一个空的HashMap:
var map = new mutable.HashMap[String,Int]()
获取指定key对应的value,如果key不存在,会报错的:
println(map("张三"))
使用contains函数检查key是否存在:
var map = Map(("张三",),("李四",),("王五",),("赵六",));
if(map.contains("张三")){
println("张三存在");
}else{
println("张三不存在");
}
使用getOrElse函数用来判断是否存在,不存在返回一个默认值:
var map = Map(("张三",),("李四",),("王五",),("赵六",));
var result = map.getOrElse("张三三",)
println(result)
更新Map的元素:
var map = Map(("张三",),("李四",),("王五",),("赵六",));
map("张三") = ;
println(map("张三"))
增加多个元素:
var map = Map(("张三",),("李四",),("王五",),("赵六",));
map += ("小明" -> ,"小红" -> );
println(map.toBuffer)
移除元素:
var map = Map(("张三",),("李四",),("王五",),("赵六",));
map -= "张三";
println(map.toBuffer);
更新不可变的map:
var map = Map(("张三",),("李四",),("王五",),("赵六",));
map -= "张三";//而不是map不可以添加和减少对应的key-value
//map("李四") = 20;//注意不可更改是key对应的value不可以改变。
println(map.toBuffer);
map += ("张三" -> );
println(map.toBuffer)
移除不可变的map的元素:
var map = Map(("张三",),("李四",),("王五",),("赵六",));
var map2 = map + ("小红" -> ,"小明" -> );
println(map2.toBuffer)
var map3 = map2 - ("小红","小明");
println(map3.toBuffer)
:Scala遍历Map的操作:
scala遍历map的entrySet:
var map = Map(("张三",),("李四",),("王五",),("赵六",));
for((key,value) <- map){
println(key + " " + value)
}
scala遍历map的key:
var map = Map(("张三",),("李四",),("王五",),("赵六",));
for(key <- map.keySet){
println(key + " " + map(key))
}
scala遍历map的value:
var map = Map(("张三",),("李四",),("王五",),("赵六",));
for(value <- map.values){
println(value)
}
scala生成新的map,反转key和value:
var map = Map(("张三",),("李四",),("王五",),("赵六",));
var result = for((key,value) <- map) yield (value,key)
for((key,value) <- result){
println(key + " " + value)
}
SortedMap可以自动对Map的key进行排序:
var map = SortedMap("张三" -> , "别先生" -> ,"小明" ->);
println(map.toBuffer)
LinkedHashMap可以记住插入的entry的顺序:
var map = new mutable.LinkedHashMap[String ,Int]();
map("张三") = ;
map("别先生") = ;
map("小明") = ;
println(map.toBuffer)
for((key,value) <- map){
println(key + " " + value)
}
:Scala的tuple:
简单Tuple和访问Tuple:
var tuple = ("张三",,,true,"李四");
println(tuple._1)
println(tuple._2)
println(tuple._3)
println(tuple._4)
println(tuple._5)
zip操作:
var names = Array("张三","李四","王五");
var ages = Array(,,);
var result = names.zip(ages);
println(result.toBuffer)
for((name,age) <- result){
println(name+ " " + age)
}
待续......
Scala学习教程笔记一之基础语法,条件控制,循环控制,函数,数组,集合的更多相关文章
- Scala学习教程笔记二之函数式编程、Object对象、伴生对象、继承、Trait、
1:Scala之函数式编程学习笔记: :Scala函数式编程学习: 1.1:Scala定义一个简单的类,包含field以及方法,创建类的对象,并且调用其方法: class User { private ...
- Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、
1:Scala和Java的对比: 1.1:Scala中的函数是Java中完全没有的概念.因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象,而且只 ...
- python学习第四讲,python基础语法之判断语句,循环语句
目录 python学习第四讲,python基础语法之判断语句,选择语句,循环语句 一丶判断语句 if 1.if 语法 2. if else 语法 3. if 进阶 if elif else 二丶运算符 ...
- 067 01 Android 零基础入门 01 Java基础语法 08 Java方法 05 数组作为方法参数
067 01 Android 零基础入门 01 Java基础语法 08 Java方法 05 数组作为方法参数 本文知识点:数组作为方法参数 说明:因为时间紧张,本人写博客过程中只是对知识点的关键步骤进 ...
- 062 01 Android 零基础入门 01 Java基础语法 07 Java二维数组 01 二维数组应用
062 01 Android 零基础入门 01 Java基础语法 07 Java二维数组 01 二维数组应用 本文知识点:二维数组应用 二维数组的声明和创建 ? 出现空指针异常 数组的名字指向数组的第 ...
- <学习笔记 之 JQuery 基础语法>
jQuery 库 - 特性 jQuery 是一个 JavaScript 函数库. jQuery 库包含以下特性: HTML 元素选取 HTML 元素操作 CSS 操作 HTML 事件函数 JavaSc ...
- 风变编程笔记(一)-Python基础语法
第0关 print()函数与变量 1. print()函数print()函数:告诉计算机,把括号的内容显示在屏幕上 # 不带引号 print(1+1) # 让计算机读懂括号里的内容,打印最终的结果 ...
- Java编程基础阶段笔记 day04 Java基础语法(下)
day04 Java基础语法 (下) 笔记Notes要点 switch-case语句注意 switch-case题目(switchTest5) 循环执行顺序 if-else 实现3个整数排序 Stri ...
- 【php学习之路】php基础语法
一.什么是php? PHP即PHP: Hypertext Preprocessor(超文本处理器),是一种服务器端脚本语言,适用于创建web站点.开源免费 二.php能做什么? ...
随机推荐
- 在Apache Struts中利用OGNL注入
前言 本文简要介绍了Apache Struts的OGNL注入缺陷,文章中介绍使用简单的应用程序复现OGNL注入.深入研究针对公共漏洞,并理解这类漏洞. 内容 安装Apache Tomcat服务器(入门 ...
- 基于FATFS的磁盘分布
1.前言 本文主要采用FAT32文件系统的磁盘各个部分是如何划分的 2. 磁盘分布总图 如包含两个分区的磁盘整体分布如下: 图 带有两个分区的磁盘分布 2.1 MBR 图 MBR的高层视图 主引导记 ...
- [IOI2000] 邮局
## 非常神仙的 wqs 二分优化dp,又学了一招. 首先我们需要先想到一个人类智慧版的前缀和优化. # part 1:violence 然鹅在前缀和优化之前我们先考虑暴力做法:我们可以枚举 i . ...
- [PHP]session的一些要点
一.session_start([array $options=array()]) 1.只能在输出http头前启动此函数,因为如果需要改写sessid的键和值,需要在http报文头发出前就开始定义了: ...
- [C]控制外部变量访问权限的extern和static关键字
一.extern 概述 编译器是由上至下编译源文件的,当遇到一些函数引用外部全局变量,而这个变量被定义在该函数声明主体的下方,又或者引用自其它的编译单元,这个情况就需要extern来向编译器表明此变量 ...
- MVC 基于 AuthorizeAttribute 实现的登陆权限控制
代码的执行顺序是 OnAuthorization–>AuthorizeCore–>HandleUnauthorizedRequest. 如果AuthorizeCore返回false时,才会 ...
- IPFS环境安装
IPFS是一个分布式的P2P的协议,可能会取代这个http,全球的点都可能存储这个数据 IPFS搭建环境 1.首先是下载节点软件到官网下载windows版本的ipfs节点软件,如果不能访问官网的话,可 ...
- C# 防止content-type修改后上传恶意文件
以图片为例子.在上传图片的时候,使用Fiddler抓取 通过js判断文件类型是不安全的,所以通过后台来判断,代码如下: ) { HttpPostedFile file0 = Request.Files ...
- mysql服务器没有响应
第一步删除c:\windowns下面的my.ini(可以先改成其它的名字也行) 第二步打开对应安装目录下\mysql\bin\winmysqladmin.exe 输入用户名 和密码(也可以忽略此步) ...
- Android源码分析一 Android系统架构
一 Android系统架构 Linux内核层(Linux Kernel):Android系统基于Linux2.6内核,这一层为Android设备各种硬件提供了底层驱动,如显示驱动.音频驱动.照相机驱动 ...