概述

本人开始学习scala的时候,是在使用和开发spark程序的时候,在此为了整理、记录和分享scala的基础知识,我写这篇关于scala的基础知识,希望与广大读者共同学习沟通进步。如果有些代码比较简单,我就略去过分的文字说明。

SCALA常与句式的使用

变量的定义:在scala中变量有两个关键字:val和var,val:是不可变的,即不可以在此给其赋值,类似于java中被final修饰的常量,var:是可变的,即可以再次赋值,声明变量的通用格式

关键字   变量名 :变量的类型=变量值

val name: String = "wwss"
var name2: String = "tom"
val age: Int = 500 //声明变量可以将变量类型省略,scala会根据变量的值自动推断也出变量的类型
val sex = "男" //也可以使用Any作为变量的类型,Any类似于java中的Object
val color: Any = "red" //可以一次声明多个变量
val name1, name5, name3, name4: String = "旺财"

for循环:和java类似,

    //使用to方法会产生一个连续不断的区间范围,[0,10]左右两边都包含
for (i <- 0 to 10)
println(i) //使用until方法会产生一个连续不断的区间范围,但是不包含最后一个数字[0,10)
for (a <- 0 until (10))
println(a) //遍历字符串
for (s <- "abcdfeg")
println(s) //多重for循环
for (i <- 1 to 9; j <- 1 to 9) {
if (j == 9) {
println(i + "*" + j + "=" + i * j + " ")
} else {
print(i + "*" + j + "=" + i * j)
}
} //带有if守卫条件的for循环
for (i <- 0 to 10 if (i % 2 == 0))
println(i) //推导式for循环
val arr = for (i <- 0 to 5) yield i * 2
for (a <- arr) {
println(a)
} //遍历数组
val arr2 = Array(1, true, "string")
for (a <- arr2) {
println(a)
} //中断跳出for循环
breakable({
for (i <- 0 to 10) {
println(i)
if (i >= 5) {
break()
}
}
})

if 判断语句:也和java类似

//在scala中不需要添加分号作为语句块的结束符
val num = 20 //在scala中if else语句是有返回值的,
//返回值就是最后一条语句的返回值
if (num > 20) "zs" else "ls"
//因为if else 语句是有返回值的,所以可以直接将
//if else语句赋值给一个变量 //在scala中无论是方法或函数以及条件判断等都只要是有返回值都不需要加return关键字
val name = if (num > 20) "zs" else "ls"
println(name) //如果在if else语句中返回的值类型不一样,scala会自动推断出两者
//的公共类型,作为变量的类型,any
val name2 = if (num == 20) "zs" else 100
println(name2) //如果if else语句缺省了else语句块,那么其实默认是没有返回值Unit,Unit用"()"表示,
//类似于java中void
val name3 = if (num > 20) "zs"
//和上面的等价
val name4 = if (num > 20) "zs" else ()
println(name3)

打印输入输出的格式:

val name = StdIn.readLine("请输入用户名:\n")
val password = StdIn.readLine("请输入密码:\n")
if(name.equals("admin") && password.equals("admin")) {
printf("欢迎您%s登记",name)
} else {
println("你输入的用户名或者密码错误,系统自动退出")
}

while语句格式:

 var num = 0;
do {
println(num)
num += 1
} while (num <= 5) //使用break()方法跳出while循环
var num2 = 0
breakable({
while (true) {
num2 += 1
if (num2 > 5) {
break()
}
println(num2)
}
}) var flag = true
var num3 = 0
while (flag) {
num3 += 1
if (num3 > 10) {
flag = false
}
println(num3)
}

SCALA方法和函数的使用

在scala比较正规的解释是:

Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。

Scala 中的方法跟 Java 的类似,方法是组成类的一部分。

Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。

定义函数的关键字是:val

定义函数的通用格式:val  函数名=(参数列表)={函数体}

 //通用的定义格式
val f1 = (x: Int, y: Int) => {
x + y
} //先定义函数的参数列表类型,具体的函数参数在函数体中定义
val f2: (Int, Int, Int) => Int = {
(x, y, z) => {
x + y + z
}
}

定义方法的关键字是:def

定义方法的通用格式:关键字  方法名(参数列表) :方法的返回值类型={方法体}

//方法的返回值不需要使用return关键字,同时方法的最后一条语句的返回
//值作为整个方法的返回值,
//注意:如果一个方法 的返回值,那么方法 的最后一条语句的返回值一定要和方法 的返回值类型保持一致
def m1(x: Int, y: Int): Int = {
var a = 1
a += 2
x + y
} //可以省略掉方法的返回值类型,scala会自动根据最后一条语句的返回值推断出方法的返回值类型
def m2(x: Int, y: Int) = {
x + y
} //如果方法没有返回值,可以使用Unit来表示标注,表现为“()”,类似于java中的void
def m3(x: Int, y: Int): Unit = {
x + y
} //也是没有返回值的方法,在参数列表括号后面直接添加方法体括号,我们称这种方法为过程
def m3_3(x: Int, y: Int) {
println(x + y)
} //先定义方法参数列表类型,具体的参数名称在方法体中
def m4: (Int, Int, Int) => Int = {
(x, y, z) => {
x + y + z
}
} //柯理化
def m5(x: Int)(y: Int) = {
x + y
} //柯理化
def m6(x: Int) = (y: Int) => {
x + y
} //如果定义一个方法,后面方法名称后面的参数列表为空,那么在调用的时候可以加括号,也可以不加括号
def m7() = {
println("hello world")
} //如果定义一个方法,方法没有参数列表,那么在调用的时候也不能加括号,否则编译不通过
def m8 = {
println("hello scala")
} //递归方法要求我们必须写明方法的返回值类型,不能省略掉,否则报错
def m9(num: Int): Int = {
if (num <= 0) 0 else m9(num - 1)
} //当参数个数不固定时,那么这时候可以将参数定义为可变参数,可变参数要求是方法的最后一个参数
def m10(name: String, nums: Int*): Unit = {
var sum = 0
for (num <- nums) {
sum += num
}
println(name + "=" + sum)
} //在scala中,有时我们调用某些方法时,不希望给出参数的具体值,而希望使用参数自身默认的值
//此时就定义方法时使用默认参数
//在调用方法的时候,赋值是从左向右依次赋值,所以说需要把没有默认值的放在最前面
def m11(age: Int, name: String = "旺财", sex: String = "男") = {
println(name + "=" + age + "=" + sex)
}

函数和方法的区别:

1,方法中的参数列表是可选的,即:参数列表可以没有,也可以为空。比如:方法可以这样写  def me() = 10 ; def me = 10 ;

但是对于函数来说,参数列表是强制的,即:参数列表可以为空,但不能没有。比如:val f=()=>10这里的括号不能省略。

2,参数传递,函数是可以作为参数传递,函数名只是代表函数自身;方法不能作为参数传递,用的方法名的地方意味这调用,那为什么在需要函数出现的地方我们可以提供一个方法,在scala中很多高级函数,如map(),filter()等,都是要求提供一个函数作为参数。但是为什么我们可以提供一个方法呢,比如这样:val myList = List(3,56,1,4,72)。

这是因为,如果期望出现函数的地方我们提供了一个方法的话,该方法就会自动被转换成函数。

3,方法可以作为一个表达式的一部分出现(调用函数并传参),但是方法(带参方法)不能作为最终的表达式,但是函数可以作为最终的表达式出现。

scala> //定义一个方法

scala> def m(x:Int) = 2*x
m: (x: Int)Int scala> //定义一个函数 scala> val f = (x:Int) => 2*x
f: Int => Int = <function1> scala> //方法不能作为最终表达式出现 scala> m
<console>:9: error: missing arguments for method m;
follow this method with `_‘ if you want to treat it as a partially applied function
m
^ scala> //函数可以作为最终表达式出现 scala> f
res9: Int => Int = <function1>

方法转换函数的方法:

在scala中方法可以转换为函数,有两种转换方法,

1,下划线:方法名 _

2,scala会隐式转换,不需要手动转换。

def m1(x: Int, y: Int) = {
x + y
} //
/**
* m2接收三个参数,
*
* @param f 它是一个函数,接收两个参数,返回值是Int类型,在传入这个参数时,
* 传入进来的参数必须符合函数的签名
* @param y 普通参数
* @param x 普通参数
* @return
*/
def m2(f: (Int, Int) => Int, y: Int, x: Int) = {
f(x, y)
} def main(args: Array[String]): Unit = {
//通过下划线将方法转换成函数
val f1 = m1 _
println(f1) //scala会自动进行转换
val v2 = m2(m1, 1, 2)
println(v2) val foreachFunction = (x: Int) => {
println(x)
} val arr = Array(1, 2, 3, 4, 5)
arr.foreach(foreachFunction) arr.foreach((x: Int) => {
println(x)
}) arr.foreach((x) => println(x)) arr.foreach(println(_)) println("********************")
val filterFunction = (x: Int) => {
x > 3
}
arr.filter(filterFunction).foreach((x: Int) => println(x)) }

SCALA常用数据结构

数组 Array

在scala 中数组分为不可变长数组(在immutable包下)和可变长数组(在mutable包下),不可变是指长度不可变,但是数组中角标元素的值是可变的,可变长数组是指长度和角标对应的元素的值都是可变的。

/**
* 不可变数组(一旦初 始化了,数组的长度是不可变的)
*/
val arr = Array[Int](1, 2, 3, 4, 5) //如果一个数组中,有不同类型的元素,那么这个数组的类型是这些元素的公共类型Any
val arr2: Array[Any] = Array("true", 1, true, "aaa") //创建一个数组,给数组初始化了长度为5,每个角标的初始值和泛型的初始值一致,也就是0
val arr3 = new Array[Int](5)
//创建一个数组,数组的长度是1,这个元素的值是5
val arr4 = Array(5) //++运算符是将两个数组添加到新的数组中去,原来的数组并没有改变,只是形成了一个新的数组
val arr5 = arr ++ arr4 /**
* 可变长数组
*/
val buffer1 = ArrayBuffer[Int]()
//如果是+=符号,那么后面只能跟单个元素
buffer1 += 1
buffer1 += 2
//++=后面不能添加单个元素,只能添加数组集合
buffer1 ++= Array(7, 8, 9)
buffer1 ++= ArrayBuffer(1, 2, 3, 4, 5, 6)
//这种添加方式是错误,
//buffer1(12) = 10 //这种方式是修改角标元素的值,不是添加值 buffer1.append(10, 11, 12) buffer1 -= 1
buffer1 -= 2
buffer1 --= Array(1, 2, 3, 4) //移除下标为5的对应的元素
buffer1.remove(5)
//从指定角标开始,移除指定个数的元素
buffer1.remove(1, 2) println(buffer1) /**
* 数组的常用方法
*/
val array = Array(1, 2, 3, 4, 5) //最大值
println(array.max)
//最小值
println(array.min)
//mkString 拼接
println(array.mkString) println(array.mkString(",")) println(array.mkString("[", ",", "]")) //reverse相当于将数组反转
println(array.reverse.toBuffer) /**
* 数组的转换操作
*/
val intArr = Array(1, 2, 3, 4, 5, 6) intArr
.map((x: Int) => x * 2)
.sortBy((x: Int) => x) //从小到大排序,即升序
.reverse //将数组反转
.foreach((x: Int) => println(x)) println("************")
intArr.map(_ * 2).sortBy(x => x).reverse.foreach(println(_)) val strArr = Array("hello you", "hello me") strArr
//Array(Array("hello","you"),Array("hello","me"))-->Array(hello,you,hello,me)
.map(x => {
val fields = x.split(" ")
fields
})
//Array(hello,you,hello,me)
.flatten
.foreach(println(_)) println("***************")
strArr.flatMap((x: String) => x.split(" ")).foreach(println(_)) }

序列

序列分为可变长序列和不可变长的,序列就是List,底层是链表结构,特点:插入有序,可重复,增加和移除元素很快,查询慢,不可变长序列:List。 可变长序列:ListBuffer

/**
* 不可变长序列List,长度不可变,角标元素也不可变
*/
val list0 = List(1, 2, 3, 4, 5) //++并没有改变原有的list,只是将两个list序列进行合并形成一个新的list
val list1 = list0 ++ List(6, 7, 8, 9)
println(list1.toBuffer)
println(list0.toBuffer) println("#####################") /**
* 定义可变长度序列
*/
val lb0 = ListBuffer(1, 2)
//+=或-=后面只能跟一个单个的元素
lb0 += 3
lb0 -= 3
//++=或--=后面只能跟一个序列list或者listbuffer
lb0 ++= List(4, 5, 6)
lb0 --= List(4, 5)
lb0 ++= ListBuffer(8, 9, 10)
lb0.append(11, 12) //移除指定角标的元素
lb0.remove(0)
//从指定角标开始,移除指定个数的元素
lb0.remove(1, 2) println(lb0) println("****************ccccc************")
/**
* 给list头部添加元素
*/
val list01 = List(4, 5, 6);
//注意,这里并不是将元素添加到list01里面,而是将list01和后面的元素(1,2,3)进行合并 ,然后形成一个新的list
//newList,需要注意的是后面的(1,2,3)是作为一个整体和list01进行合并
var newList = list01.::(1, 2, 3)
println(newList)
println(list01)
newList = list01.+:(1, 2, 3)
println(newList) newList = (1, 2, 3) :: list0
println(newList) newList = (1, 2, 3) +: list01
println(newList) //这里是将1,2,3进行拆分开同list01进行合并
newList = List(1, 2, 3) ++ list01
println(newList) println("$$$$$$$$$$$$$$$$$$$$$$") /**
* 给list尾部添加元素
*/
val list02 = List(4, 5, 6)
//这里也是将(7,8,9)作为整体同list02进行合并 添加到尾部,形成一个新的list
var newList02 = list02.:+(7, 8, 9)
println(newList02) //将7,8,9进行拆分同list02进行合并插入到list02后面去,形成一个新的list,原来的list并没有改变
newList02 = list02 ++ List(7, 8, 9)
println(newList02) /**
* 序列的常用操作方法
*/
val lt = List(1, 2, 3, 4, 5)
//求和
println(lt.sum)
//最大值
println(lt.max)
//最小值
println(lt.min)
//第一人元素
println(lt.head)
//最后一个元素
println(lt.last)
//反转序列形成一个新的list,原来的list不会被改变
println(lt.reverse)
//拼接
println(lt.mkString)
println(lt.mkString(","))
println(lt.mkString("[", ",", "]")) /**
* 序列的转换操作
*/
val lit = List(1, 2, 3, 4, 5, 6, 6,7,7, 8)
lit.map(_ * 2).filter(x => x > 10).distinct.reverse.foreach(println(_))

map的使用:map分为可变长和不可变长

 /**
* 不可变长Map映射,长度和值一旦初始化后不能再次被改变
*/ //通过对偶元组的方法创建映射
val map0 = Map(("a", "A"), ("b", "B"), ("c", "C"))
// 通过箭头方式创建Map映射
val map1 = Map("a" -> "A", "b" -> "B", "c" -> "C")
//两者进行混合创建Map映射
val map3 = Map("a" -> "A", ("b", "B"), ("c", "C")) //++只是将两个映射合并形成新的map映射,原有的map映射并没有改变
val newMap = map0 ++ map1
println(newMap) /**
* 可变长map映射,mutable包下
*/ val map4 = mutable.Map("a" -> "A")
map4.put("b", "B")
map4 += ("c" -> "C", "d" -> "D")
map4 += (("e", "E"), ("f", "F"))
map4 ++= mutable.Map("j" -> "J", "h" -> "H", ("i", "I"))
println(map4) /**
* 移除map中的key
*/
map4 -= "i"
println(map4)
map4 --= Set("i", "j", "f")
println(map4)
map4.remove("h")
println(map4) /**
* Map映射常用操作方法
*/
//判断一个key是否存在,存在返回true,否则返回false
println(map4.contains("a"))
//获取key对应的值,注意如果通过map("Key")获取对应的值,应该进行key是否存在判断
if (map4.contains("e")) {
println(map4("e"))
} //映射的get方法也是用来获取key对应的值,但是这个方法返回的是一个option对象,这个option对象有两个
//子类,如果有key则返回Some(some对象中封装了key对应的值,可以通过Some的get方法获取值)对象,没有key则返回None对象
println(map4.get("e").get)
val value: Option[String] = map4.get("e")
//isEmpty方法可以用来判断是Some对象还是None
if (!value.isEmpty) {
println(value.get)
} else {
println(value)
} //如果key存在,则返回key对应的value,否则返回给定的默认值
val v = map4.getOrElse("e", "EE")
println(v) println("********************************")
/**
* LinkedHashMap 插入有序,会按照我们的插入顺序排序,因为底层是链表结构
*/
val map5 = mutable.LinkedHashMap[String, String]()
map5 += ("d" -> "D")
map5 += (("a", "A"))
map5("c") = "C"
map5("b") = "B"
println(map5) /**
* SortedMap可以自动对Map的key进行排序
*/
val map6 = mutable.SortedMap[String, String]()
map6("c") = "C"
map6("b") = "B"
map6("a") = "A"
println(map6)

set集合

特点和java一样无顺序不重复

/**
* 不可变长set集合
*/
val set0 = Set(1, 2, 3, 4, 5)
//++并没改变原有的set集合,只是将两个set进行合并形成新的set集合
val newSet0 = set0 ++ Set(6, 7, 8, 9)
println(newSet0) /**
* 可变长set集合
*/
val set1 = mutable.Set(1, 3)
//+=或-=后面只能是半单个元素
set1 += 1
set1 += 2
//++=或者 --=后面只能添加set集合
set1 ++= mutable.Set(5, 6, 7)
set1.add(12)
println(set1) set1 -= 1
set1 --= mutable.Set(1, 2, 3)
println(set1) /**
* set常用操作方法
*/
println(set1.mkString(","))
println(set1.size)
println(set1.head)
println(set1.last)
println(set1.max)
println(set1.min)
println(set1.sum) /**
* set的转换操作
*/
set1.map(_ * 2).filter(x => x > 2).foreach(println(_))

元组的使用

scala的元组是用括号来表示的,获取元组的值用下划线来表示,角标从1开始。

//定义一个元组
val t1 = ("小明", "男", 25)
//元组的下标是从1开始
println(t1._1 + "=" + t1._2 + "=" + t1._3) //只有两个元素的元组被称之为对偶元组(key-value)
val tuple2 = ("id", "123")
println(tuple2._1 + "-" + tuple2._2) //可以将元组中的元素单独赋值给对应的变量
val tuple3, (name, age, sex) = ("ximing", 12, "男")
println(tuple3)
println(name)
println(age)
println(sex) //数组的拉链操作转换成元组,如果数组中有多余的就会被舍弃掉
val arr1 = Array("a", "b", "c", "d","e")
val arr2 = Array("A", "B", "C", "D") val arr3: Array[(String, String)] = arr1.zip(arr2)
println(arr3.toBuffer)

结束

本文没什么技术含量,只是闲暇是对自己知识的反复练习和记录。希望对读者有溢。

SCALA-基础知识学习(一)的更多相关文章

  1. SCALA基础知识学习

    注:本文只说和Java不同的地方. 总结自: Scala详细教程 Scala教程 scala基础语法 Scala 与 Java 的最大区别是:Scala 语句末尾的分号 ";" 是 ...

  2. GCC基础知识学习

    GCC基础知识学习 一.GCC编译选项解析 常用编译选项 命令格式:gcc [选项] [文件名] -E:仅执行编译预处理: -S:将C代码转换为汇编代码: -c:仅执行编译操作,不进行连接操作: -o ...

  3. (转)Linux基础知识学习

    Linux基础知识学习 原文:http://blog.csdn.net/ye_wei_yang/article/details/52777499 一.Linux的磁盘分区及目录 Linux的配置是通过 ...

  4. Objective-c基础知识学习笔记

    Objective-c基础知识学习笔记(一) 一直有记录笔记的习惯.但非常久没分享一些东西了,正好上半年開始学习IOS了,如今有空写点.因开发须要,公司特意为我们配置了几台新MAC.还让我们自学了2周 ...

  5. AXAJ基础知识学习

    AXAJ基础知识学习 博客首页 Ajax简介 ajxa全称是Asynchronous Javascript And XML ,就是异步的JS 和XML 通过Ajax可以再浏览器中向服务器发送异步请求, ...

  6. Vue2基础知识学习

    Vue2基础知识学习 01.初识 new Vue({ el: '#root', //用于指定当前Vue实例为哪个容器服务,值通常为css选择器符 data () { return { } } }); ...

  7. C#基础知识学习

    C#基础知识整理 学习地址:http://blog.csdn.net/column/details/csarp.html

  8. 韩天峰博客 php基础知识学习记录

    http://rango.swoole.com 写好PHP代码真的不容易,给大家几个建议: 慎用全局变量,全局变量不好管理的,会导致你的代码依赖于全局变量,而耦合度太高. 一定不要复制粘贴代码,可重用 ...

  9. scala 基础知识总结

    在最开始处引入 log 相关的 包 import org.apache.log4j.{Logger,Level} 在需要屏蔽日志输出的地方加上这两行代码 // 屏蔽不必要的日志显示在终端上 Logge ...

  10. 〖前端开发〗HTML/CSS基础知识学习笔记

    经过一天的学习,把慕课网的HTML/CSS基础知识学完了,笔记整理: 1. 文件结构: HTML文件的固定结构: <html> <head>...</head> & ...

随机推荐

  1. Excel如何使用vlookup

    一.vlookup的语法 VLOOKUP (lookup_value, table_array, col_index_num, [range_lookup]) ①Lookup_value为需要在数据表 ...

  2. LightningChart .NET v.10.2.1已经发布了!

    LightningChart .NET v.10.2.1已经发布了! 了解更多关于兼容性和优化方面的最新改进. 主要改进 我们很高兴地宣布LightningChart .NET产品系列的第三个主要版本 ...

  3. ciscn_2019_n_8 1

    拿到题目老样子先判断是多少位的程序 可以看到是32位的程序,然后再查看开启的保护 然后将程序放入ida进行汇编 先shift+f12查看程序是否有system和binsh 可以看到有system和bi ...

  4. 测试开发实战[提测平台]17-Flask&Vue文件上传实现

    微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 先回顾下在此系列第8次分享给出的预期实现的产品原型和需求说明,如下图整体上和前两节实现很相似,只不过一般测试报告要写的内容可能比较多,就多 ...

  5. CF420A Start Up 题解

    Content 给定一个长度为 \(n\) 的字符串,求这个字符串整个反转过来后是否和原字符串一样. 数据范围:\(1\leqslant n\leqslant 10^5\). Solution 众所周 ...

  6. linux安装软件系列之npm安装

    什么是rpm 百度说它是 Red-hat Package Manager (红帽包管理器) 其实它是:RPM Package Manager (RPM包管理器,来源于:https://rpm.org) ...

  7. centos7使用Dockerfile(docker-compose)运行jar包

    Dockerfile文件 FROM openjdk:8-jdk-alpine MAINTAINER "镜像维护者的姓名和邮箱地址" WORKDIR app ADD demo.jar ...

  8. 【LeetCode】1171. Remove Zero Sum Consecutive Nodes from Linked List 解题报告 (C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 preSum + 字典 日期 题目地址:https:/ ...

  9. 【九度OJ】题目1087:约数的个数 解题报告

    [九度OJ]题目1087:约数的个数 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1087 题目描述: 输入n个整数,依次 ...

  10. 【LeetCode】968. Binary Tree Cameras 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...