Scala(一)-- 语法简介

Scala结合了面向对象和函数式编程,具备静态类型特性,常用于高性能系统和大数据处理。学习Scala的原因包括速度快、简洁优雅、融入Hadoop生态圈。本文介绍了Scala的特点、环境准备,并详细讲解了变量定义、数据类型、类型转换、操作符、条件表达式、块表达式、循环语句、方法、函数、数组、映射、元组、列表、集合等基础语法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

scala

Scala(Scalable Language)以一种简洁、高级的语言将面向对象函数式编程结合在一起.Scala的静态类型有助于避免复杂应用程序中的bug,它的JVM和JavaScript运行时允许您构建高性能的系统,可以轻松地访问庞大的库生态系统。

1、scala的特点:

(1)、面向对象

scala是一个纯面向对象的语言,所有的值都是对象、类和对象行为用类和特质来描述

(2)、函数式编程(项目的组成是函数)

纯函数(没有副作用)、一个参数输入,输出是确定的(中间没有涉及到其他变量、数据结构的修改,没有打印),函数要求比较高,所有函数都是值

函数等于一个值,可以作为一个普通的变量去使用
(面向过程)

(3)、静态类型

-类型在编译阶段确定–静态语言 类型在运行阶段确定–动态语言
-强类型语言:(类型转换时确定)必须强制类型转换 弱类型语言:自动类型转换

基于jvm,高性能,先编译为java的class文件,再去运行

2、为什么学scala?

1、速度快:Scala语言表达能力强,一行代码抵得上Java多行,开发速度快;Scala是静态编译的,所以和JRuby,Groovy比起来速度会快很多
2、简洁优雅:api优雅,spark源码是scala写的
3、能融合到Hadoop生态圈:Hadoop现在是大数据事实标准,Spark并不是要取代Hadoop,而是要完善Hadoop生态。JVM语言大部分可能会想到Java,但Java做出来的API太丑,或者想实现一个优雅的API太费劲。

3、环境准备

jdk1.8 、开发工具idea、安装scala

注意:路径不要有中文、空格
安装idea
安装idea 插件
解压scala
配置环境变量(SCALA_HOME、PATH)

Scala语法:

1.变量定义###

var 变量名:变量类型=初始化值 (能修改)
val 变量名:变量类型=初始化值 (不能修改)

//变量名在前,变量类型在后
scala> val str:String = "hello"
str: String = hello

scala> val t1 = 3
t1: Int = 3

scala> t1 = 5
<console>:8: error: reassignment to val
       t1 = 5
          ^

scala> var t2 = 3
t2: Int = 3

scala> t2 = 5
t2: Int = 5

scala中:
var修饰的变量,内容和引用都可变
val修饰的变量是不可变的,注意不可变的不是内容,而是引用

举例:
scala> val arr = Array(1,2,3,4)
arr: Array[Int] = Array(1, 2, 3, 4)

scala> arr(1)
res2: Int = 2

scala> println(arr)
[I@7b22ec89

scala> arr
res4: Array[Int] = Array(1, 2, 3, 4)

scala> val arr1 = Array(5,43,65)
arr1: Array[Int] = Array(5, 43, 65)

scala> arr=arr1
<console>:9: error: reassignment to val
       arr=arr1
          ^

scala> arr(1)=55

scala> arr
res6: Array[Int] = Array(1, 55, 3, 4)

val修饰的变量,相当于Java中final修饰的变量

可以加lazy修饰变量(只有val修饰的变量才能被lazy修饰),先不赋值,使用时再赋值

scala> lazy val t = 56
t: Int = <lazy>

scala> t
res7: Int = 56

注意:

1)可以不写类型,根据赋值去判断
2)val修饰的变量不能修改,但val修饰的变量是引用类型时可以修改(举例数组)
3)可以加lazy修饰变量(只有val修饰的变量才能被lazy修饰),先不赋值,使用时再赋值(lazy val j = 100)

2.数据类型

(数值类型 引用类型)
Scala和Java一样,有8种数值类型Byte、Char、Short、Int、Long、Float、Double和一个Boolean类型,和Java不同的是 ,Scala没有基本类型与包装类型之分,这些类型都是类,有自己的属性和方法。

Unit是值类型,他只有一个实例对象()。
Nothing是所有类型的子类,他没有一个具体的实例对象,一个常见的应用如:抛出异常、程序exit,无限循环等。
Nothing是所有类型的子类,也是Null的子类。Nothing没有对象,但是可以用来定义类型。例如,如果一个方法抛出异常,则异常的返回值类型就是Nothing(虽然不会返回) 。
Null是所有引用类型的子类,它只有一个实例对象null,主要用来和其他的JVM语言进行互操作。

详解:

数据类型 描述
Byte 8位有符号补码整数。数值区间为 -128 到 127
Short 16位有符号补码整数。数值区间为 -32768 到 32767
Int 32位有符号补码整数。数值区间为 -2147483648 到 2147483647
Long 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807
Float 32 位, IEEE 754 标准的单精度浮点数
Double 64 位 IEEE 754 标准的双精度浮点数
Char 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF
String 字符序列
Boolean true或false
Unit 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。
Null null 或空引用
Nothing Nothing类型在Scala的类层级的最低端;它是任何其他类型的子类型。
Any Any是所有其他类的超类
AnyRef AnyRef类是Scala里所有引用类(reference class)的基类
上表中列出的数据类型都是对象,也就是说scala没有java中的原生类型。在scala是可以对数字等基础类型调用方法的。

3.Scala类型转换

如:char.toInt(调用方法)

scala> val ch:Char = 'A'
ch: Char = A

scala> ch.toInt
res11: Int = 65

4.Scala操作符

Scala中没有操作符,只是以操作符的格式去进行方法调用。没有++ --,所有操作符都是方法 。

//算术运算符
+、-、* 、/、%
//关系操作符
> < >= <= != ==
//逻辑操作符
&& || !
//位操作符
| & ^ ~ << >> >>>
~:补运算符,是一元的,具有‘翻转’位的效应。
>>:带符号右移。正数右移高位补0,负数右移高位补1。
>>>:无符号右移。无论是正数还是负数,高位通通补0。
//赋值运算符
= += -= *= /= %= <<= >>= &= ^= |=

运算符优先级:不清楚时使用()进行操作

注意:

1)a + b 等价于 a.+(b)
2)Scala没有++,-- 可以用+=,-=代替
3)操作符都是方法的重载,是方法的调用

5.条件表达式

if/else表达式有值,这个值就是跟在if或者else之后的表达式的值
(条件成立/不成立)

val x = 2
if(x>0) 1 else -1

scala> val z = if(x>0) "success" else -1
z: Any = success

混合式的条件表达式,返回类型是Any

val z = if(x<0) "success"   缺失else的条件表达式,相当于:
val z = if(x<0) "success" else ()

if 嵌套 (if… else if… else…)

val n = if(x<0) 0 else if(x>=1) 1 else -1

注意:
1)每个表达式都有一个类型
2)条件表达式有值,不能在里面赋值
3)混合型表达式,结果是Any或者AnyVal
4)scala没有switch语句

6.块表达式 ### {}

在Scala中,{}中可以包含一系列表达式,块中最后一个表达式的值就是块的值

val x0 = 1
val y0 = 1
val x1 = 2
val y1 = 2

val distance = {
  val dx = x1 - x0
  val dy = y1 - y0
  Math.sqrt(dx*dx+dy*dy)
}
println(distance)

val res1 = {
  val dx = x1 - x0
  val dy = y1 - y0
  val res = Math.sqrt(dx*dx+dy*dy)
}
println(res1)


结果为:
1.4142135623730951
()

注意:

1)块表达式的值是最后一个表达式的值
2)赋值语句的值是Unit类型的,它的唯一实例是()

7.循环语句

在scala中有for循环和while循环,用for循环比较多
循环语法结构:

for (i <- 表达式/数组/集合)
while (条件语句){表达式}
do{表达式}while()

for (i <-1 to 10) println(i)
for (i <- 1 until 10) println(i)//until包左不包右

val s = "Hello"
for (i <- 0 to s.length-1) { // 0 until s.length
  println(s(i))
}

//高级for循环
for(i <- 1 to 3;j <-1 to 3 if i == j){
  //println(s"i+j=$i+$j")
  println((10*i+j)+"")
  println()
}

//for推导:如果for循环的循环体以yield开始,则该循环会构建一个集合或者数组,每次迭代生成其中一个值
val v = for(i <- 1 to 10 )yield i*10
println(v)

如何跳出循环?
Scala里面没有break、contine关键字,推荐使用函数式的风格解决break和contine的功能

跳出循环(要导包实现)

注意:
首先要导包
import scala.util.control.Breaks._

break:breakable()包住整个循环体 
//break例子
breakable(
for (i <- 1 to 10){
  if(i==5){
    break()
  }
  println("i="+i)
})

continue:breakable()包住判断条件
//continue例子
for(j <-1 to 10){
  breakable(
  if(j==5){
    break;
  })
  println("j="+j)
}

8.方法

方法定义方式:

def 方法名 (参数列表):返回值类型= {方法体}

scala> def add(x:Int,y:Int):Int=x+y
add: (x: Int, y: Int)Int

scala> add(1,2)
res15: Int = 3

带有多参数列表的方法:

scala> def addThenMultiply(x:Int,y:Int)(multiplier:Int):Int=(x+y)* multiplier
addThenMultiply: (x: Int, y: Int)(multiplier: Int)Int
scala> addThenMultiply(2,3)(4)
res17: Int = 20

无参方法:

scala> def name:String = System.getProperty("user.name")
name: String

scala> name
res19: String = brz

方法体是多行语句的表达式

scala> def area(length:Int,wide:Int):Int={
     | val area = length * wide
     | area}
area: (length: Int, wide: Int)Int

scala> area(4,5)
res20: Int = 20

定义默认值参数(一个方法的返回值大部分条件下返回一个值时)
带有默认值的方法:默认参数可以有多个,对位置也不做要求,传值默认是按顺序传的,可以带名称传值

def method1(a:Int=1,b:Int,c:Int=3) = println("a="+a+"b="+b+"c="+c)
//调用
method1(b=2) //不能method1(2)
//或者
method1(1,2) //method1(a=1,b=2)
//或者
method1(1,2,3) //method1(c=1,b=2,a=3)

可变参数或不定长参数

scala> def varele(a:Int*){
     | for(i<-a){
     | println(i)}
     | }
varele: (a: Int*)Unit

scala> varele(1,2,3,4)
1
2
3
4

scala> var arr = Array(1,2,3,4)
arr: Array[Int] = Array(1, 2, 3, 4)

scala> varele(arr:_*)
1
2
3
4

注意1:可变参数一定是参数列表的最后一个参数

注意2:函数内部,重复参数的类型是声明参数类型的数组,但是如果你给一个可变参数的方法传一个数组,是会报编译错误:type mismatch,可以使用数组名:_*的方式传参

注意:

1)方法的返回值类型可以不写,编译器可以自动推断出来,但是对于递归函数,必须指定返回类型
2)方法的返回值默认是方法体中最后一行表达式的值,当然也可以用return来执行返回值,但不推荐这么做。
3)若使用 return 来制定函数的返回值,scala的类型推断将会失效,要显式指定返回值类型。
4)方法也可以没有返回值(返回值是Unit)

9.函数

给方法传递一个函数类型的参数:

def foo(f: Int => String) = …
def bar(f:(Boolean,Double)=>List[String])=…
函数可以看做是带有参数的表达式。

函数的定义方式:

-1-

val f1 = (a: Int, b: Int) => a + b   //推荐使用这种定义方式
val f2 = ((a: Int, b: Int) => a + b)
val f3 = (_: Int) + (_: Int)
val f4: (Int, Int) => Int = (_ + _) 

-2-

val f1:((Int,Int)=>Int)={(x,y)=>x+y}
val f2:(Int,Int)=>Int =(x,y)=>x+y

-3-

val f1 = new Function2[Int, Int, Int] {
def apply(x: Int, y: Int): Int = if (x < y) y else x
}

匿名函数:

(x:Int)=>x+1

多参数函数:

val ff = (x:Int,y:Int)=>x+y

无参函数:

scala> val getTheAnswer = () => 42
getTheAnswer: () => Int = <function0>

scala> println(getTheAnswer())
42

scala> println(getTheAnser)
<function0>

方法和函数的区别:

方法和函数的定义语法不同
方法一般定义在某个类、特质、或者object中
方法可以共享使用所在类内的属性

在函数式编程语言中,函数是“头等公民”,可以调用它,也可以传递它,存放在变量中,或者作为参数传递给另一个函数


举例:首先定义一个方法,再定义一个函数,然后将函数传递到方法里面

scala> def m(f:(Int,Int)=>Int)=f(2,6)
m: (f: (Int, Int) => Int)Int

scala> val f2 = (x:Int,y:Int)=>x-y
f2: (Int, Int) => Int = <function2>

scala> m(f2)
res37: Int = -4

将方法 转化为 函数:

把方法作为参数传给另一个方法或者函数的时候,方法被转化成函数,使用下划线(“ ”,“,_”)

scala> def ff(x:Int,y:Int)=x+y
ff: (x: Int, y: Int)Int

scala> ff _
res38: (Int, Int) => Int = <function2>

scala> ff(_,_)
res39: (Int, Int) => Int = <function2>

###(10)集合 ###
集合是一种用来存储各种对象和数据的容器,Scala 集合分为可变的和不可变的集合。
可变集合可以在适当的地方被更新或扩展。这意味着你可以修改,添加,移除一个集合的元素;而不可变集合类,相比之下,永远不会改变。不过,你仍然可以模拟添加,移除或更新操作。但是这些操作将在每一种情况下都返回一个新的集合,同时使原来的集合不发生改变。

可变集合                   不可变集合(推荐使用)
对值得删除修改添加扩容
可以(在之前的上直接改)      不可以(模拟修改得到新的集合)

推荐使用不可变的集合,效率高,占空间少,如果需要,可以转换为可变的集合
https://docs.scala-lang.org/overviews/collections/overview.html


了解集合的区别、创建、方法

11.数组(Array)

数组元素内容要求类型一致。

定长数组,数组不可扩容
变长数组,数组可扩容

定长数组

1)创建一个定长数组的方式:

(1)使用new关键字创建一个定长数组:
val arr2 = new ArrayInt

(2)直接使用Array创建并初始化一个数组:
val arr1 = ArrayInt

注意:

val arr1 = ArrayInt//初始化一个长度为1,值为10的定长数组
val arr2 = new ArrayInt 初始化一个长度为10的定长数组,其所有元素均为0

scalaval arr1 = ArrayInt
arr1: Array[Int] = Array(10)

scalaval arr2 =new ArrayInt
arr2: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

//初始化一个长度为9的定长数组,其所有元素均为0
val arr1 = new Array[Int](9)
println(arr1)//直接打印定长数组,内容为数组的hashcode值
//将数组转换成数组缓冲,就可以看到原数组中的内容了
println(arr1.toBuffer)//toBuffer会将数组转换长数组缓冲

//初始化一个长度为1,值为9的定长数组
val arr2 = Array[Int](9)
println(arr2.toBuffer)

//使用()来访问元素
println(arr2(0))//下标从0开始

//遍历数组
for(i<-0 to arr1.length-1){
  println(arr1(i))
}

//访问并修改元素值
arr1(5)
arr1(6)=10
for(i<-0 until arr1.length){
  print(s"$i:${(arr1(i))}")
  println()
}

2)变长数组
定义变长数组的方式(2种):
import scala.collection.mutable.ArrayBuffer
var arr3 = ArrayBufferInt//定义一个空的可变长Int型数组
var arr4 = ArrayBufferInt //初始值为10

new时会创建一个长度为0的数组
var arr5 = new ArrayBuffer[Int](10)
等价于
var arr5 = new ArrayBuffer[Int]()

3)数组的增删改

-1-添加元素

//使用+=在尾端添加一个或者多个元素
arr5 += 1  
arr5 += (2,3,4)  

//使用++=在尾端添加任何集合
arr5 ++= Array(5,6,7)  

//使用append追加一个或者多个元素
arr5.append(8)  
arr5.append(9,10)

//在下标2之前插入元素
arr5.insert(2,20)
arr5.insert(2,30,30)

-2-移除:

arr5 -= 20
arr5 --= Array(20,9)

arr5.trimEnd(2)  从尾部移除2个元素
arr5.trimStart(2)  从头部部移除2个元素

//从下标2出移除一个或者多个元素
arr5.remove(2)
arr5.remove(2,2)

-3-修改

arr5(1)=10

-4-数组遍历

(1).增强for循环
for(item <- arr5) println(item)
(2).好用的until会生成脚标
for(i <- 0 until arr5.length) println(arr5(i))

4)定长数组与变长数组的转换

定长--> 变长
val arr6 = Array(1,2,3)
arr6.toBuffer
arr6.toArray

5)数组转换

yield关键字将原始的数组进行转换会产生一个新的数组,原始的数组不变

//使用for推导生成一个新的数组
val a = Array(1,2,3,4,5,6,7,8,9)

val res1 = for(i<-a)yield i*2
for(m<-res1){
  println(m)
}

//对原数组元素过滤后生成一个新的数组
//将偶数取出乘以10后再生成一个新的数组
val res2 = for(i<-a if i%2 == 0) yield 10*i
for (n<-res2){
  println(n)
}

//使用filter和map转换出新的数组
val res3 = a.filter(_%2==0).map(10 * _)
for (q<-res2){
  println(q)
}	

6)数组常用方法

arr6.sum//求和
arr6.max//最大值
arr6.min//最小值
arr6.sorted//排序
arr6.sortWith(_>_)//指定排序方式

12.映射(Map)###

在Scala中,把哈希表这种数据结构叫做映射

1)构建映射

在Scala中,有两种Map,一个是immutable包下的Map,该Map中的内容不可变;另一个是mutable包下的Map,该Map中的内容可变。

(1)构建一个不可变的map

val scores = Map("zhangsan"->90,"lisi"->80,"wangwu"->70)
val scores = Map(("zhangsan",90),("lisi",80),("wangwu",70))

(2)构建一个可变的map

val scores = scala.collection.mutable.Map(("zhangsan",90),("lisi",80),("wangwu",70))

2)访问映射中的值

根据键获取map中对应的值,可以有以下三种方法,尤其推荐使用getOrElse方法。

val score1 = scores("lisi")
val score2 = if(scores.contains("lisi")) scores("lisi") else 0
val score3 = scores.getOrElse("lisi",0)  //0为默认值,如果不存在则返回默认值

3)修改键对应的值

scores("tom") = 99  
scores("tom11") = 99  不存在时会添加一个值
scores.update("tom",66)

4)添加、移除键值对
scores +=(“mary”->55)
scores - “tom”

scores ++= Map("tom"->55,"mary1"->44)  
scores --= List("mary","tom")
  1. 遍历map

    val keys = scores.keySet set集合
    val key = scores.keys 返回一个迭代器
    val value = scores.values 返回值的迭代器

    for((k,v)<-scores) println(k+" “+v) 返回键值对
    for (item <- scores) print(item+” ") 返回键值对

6)HashMap(可变map)

val hashmap = new scala.collection.mutable.HashMap[String,Int]()
//向map中添加数据
map1("spark") = 1
map1 += (("hadoop", 2))
map1.put("storm", 3)
//从map中移除元素
map1 -= "spark"
map1.remove("hadoop")

7)TreeMap、SortedMap(有序的map)
返回按特定顺序排列的元素集合。

var treemap = scala.collection.immutable.TreeMap(3->"hadoop",1->"scala",2->"hadoop")
var SortedMap = scala.collection.immutable.SortedMap(3->"hadoop",1->"scala",2->"hadoop")

13.元组(Tuple)

映射是K/V对偶的集合,对偶是元组的最简单形式,元组可以装着多个不同类型的值,是不同类型的值的聚集

创建元组:使用小括号将多个元素括起来,元素之间用逗号分隔,元素的类型和个数任意
访问组元:使用_1, _2, _3等访问组元

(1)定义方式(2种)

定义1:val tuple = (“scala”,“spark”,1,2)

定义2:val tuple = new Tuple4(“scala”,“spark”,1,2) 元组元素个数要与Tuple4相同

取元组中的元素值
val t_1 = tuple._1

也可以通过a,b,c去访问组元
val tuple,(a,b,c)=(“scala”,“spark”,1)

目前 Scala 支持的元组最大长度为 22。对于更大长度你可以使用集合,或者扩展元组

1)元组访问:
注意元组元素的访问有下划线,并且访问下标从1开始,而不是0

val value1 = tuple._3  

2)元组遍历
方式1:

for (elem <- tuple.productIterator) {
println(elem)
}

方式2:

tuple.productIterator.foreach(i => println(i))
tuple.productIterator.foreach(print(_))

3)拉链操作
使用zip方法把元组的多个值绑在一起,以便后续处理

A zip B  

注意:如果两个数组的元素个数不一致,拉链操作后生成的数组的长度为较小的那个数组的元素个数

14.列表(List)

列表是同质的,列表中的元素类型是一致的,列表是有序的。

不可变的序列

import scala.collection.immutable._
val fruit = List("apples", "oranges", "pears")

所有的列表可以看做是由两个基础构造快Nil和中缀操作符::构成,::表示从列表前段扩展。
在Scala中列表要么为空(Nil表示空列表),要么是一个head元素加上一个tail列表。
:: 操作符是将给定的头和尾创建一个新的列表

注意:

:: 操作符是右结合的,如9 :: 5 :: 2 :: Nil相当于 9 :: (5 :: (2 :: Nil))

1)列表的访问
val nums = 1 :: 2 :: 3 :: 4 :: list0 :: Nil
nums(0)
2)列表的追加

将0插入到lst1的前面生成一个新的List ::和+:右结合

val lst1 = List(1,2,3)

//将元素0添加到lst1的前面产生一个新的集合
val lst2 = 0 :: lst1
val lst3 = lst1.::(0)
val lst4 = 0 +: lst1
val lst5 = lst1.+:(0)

//将一个元素添加到lst1的后面产生一个新的集合,:+左结合
val lst6 = lst1 :+ 3

val lst0 = List(4,5,6)
//将2个list合并成一个新的List
val lst7 = lst1 ++ lst0
//将lst1插入到lst0前面生成一个新的集合
val lst8 = lst1 ++: lst0

//将lst0插入到lst1前面生成一个新的集合
val lst9 = lst1.:::(lst0)
3)对列表的操作

对列表的所有操作可以表达为一下三种:
head 返回列表的第一个元素。
tail 返回除第一个元素之外所有元素组成的列表。
isEmpty 返回列表是否为空。

scala> lst1.head
res40: Int = 1

scala> lst1.tail
res42: List[Int] = List(2, 3)

scala> lst1.isEmpty
res43: Boolean = false

注意:其中tail head作用在空列表上,会报异常

4) 列表的常用方法
//连接操作
scala> List(1, 2) ::: List(3, 4, 5)
res8: List[Int] = List(1, 2, 3, 4, 5)

//求列表长度
scala> List(1,2,3).length

//反转列表
scala> abcde.reverse

//提取列表的前n个元素
scala> abcde take 2

//丢弃列表的前n个元素
scala> abcde drop 2

//拉链操作
scala> abcde zip List(1,2,3,4,5)
5)可变列表
import scala.collection.mutable.ListBuffer
val list = ListBuffer(1,2,3,4,5)

list += 6
list ++= List(7,8,9)
list -= 1

14.集合:set

不可变的set

val set = Set(1,2,3)

import scala.collection.immutable.HashSet
val set = new HashSet(2,3,4,5,6)  错误
var set = new HashSet[Int]()      正确

//将元素和set1合并生成一个新的set,原有set不变
set+=1  
set = set+4  不可以重复加入,(去重),无序

可变的set

import scala.collection.mutable.HashSet
var set1 = new HashSet[Int]()

set1 = set1+4
set1 += 5

基本操作:Scala集合有三个基本操作:head/tail/isEmpty
最值:查找集合中最大与最小元素 你可以使用 Set.min 方法来查找集合中的最小元素,使用 Set.max 方法查找集合中的最大元素
两个集合间的操作:可以使用 ++ 运算符或 Set.++() 方法来连接两个集合。如果元素有重复的就会移除重复的元素
交集:可以使用 Set.& 方法或 Set.intersect 方法来查看两个集合的交集元素

官网API:https://docs.scala-lang.org/

15.集合高级运用

1)集合的重要函数:sum/max/min/count

val seq = Seq(1,2,3,4,5)
seq.max
seq.min
seq.count(_%2==0) //根据条件计数

2)过滤

seq.filter(_%2==0)   返回符合Boolean条件的结果

3)map:(映射)列表元素

map函数的逻辑是遍历集合中的元素并对每个元素调用函数

scala> val seq = Seq(1,2,3,4,5)
seq: Seq[Int] = List(1, 2, 3, 4, 5)

scala> seq.map(n=>n*2)
res56: Seq[Int] = List(2, 4, 6, 8, 10)

scala> seq.map(_*2)
res57: Seq[Int] = List(2, 4, 6, 8, 10)

4)flatten、flatMap
当有一个集合的集合,然后你想对这些集合的所有元素进行操作时,就会用到 flatten。

flatten:脱壳,压平、取集合里面的元素
flatMap:先map操作,再进行flatten操作

scala> val s1 = Seq(1,2,3)
s1: Seq[Int] = List(1, 2, 3)

scala> val s2 = Seq(4,5,6)
s2: Seq[Int] = List(4, 5, 6)

scala> val s = Seq(s1,s2)
s: Seq[Seq[Int]] = List(List(1, 2, 3), List(4, 5, 6))

scala> s.flatten
res59: Seq[Int] = List(1, 2, 3, 4, 5, 6)

flatMap()
val list = List(1,2,3,4,5)
list.flatMap(n=>List(n*10,n))

scala> val list = List(1,2,3,4,5)
list: List[Int] = List(1, 2, 3, 4, 5)
	                                    //map后压平 
scala> list.flatMap(n=>List(n*10,n))    //List(List(10,1),List(20,2),List(30,3),List(40, 4),List(50, 5))
res12: List[Int] = List(10, 1, 20, 2, 30, 3, 40, 4, 50, 5)

5)集合之间的操作(差集、交集和并集)

num1.diff(num2)
num1.intersect(num2)
num1.union(num2)

如果我们不需要重复怎么办?这时可以使用 distinct 函数

num1.union(num2).distinct

6) 对整个集合进行条件检查
确保集合中所有元素都要符合某些要求,如果有哪怕一个元素不符合条件,就需要进行一些处理:

scala> val numbers = Seq(3, 7, 2, 9, 6, 5, 1, 4, 2)
numbers: Seq[Int] = List(3, 7, 2, 9, 6, 5, 1, 4, 2)

scala> numbers.forall(n => n < 10)
res64: Boolean = true

scala> numbers.forall(n => n > 5)
res65: Boolean = false

而 forall 函数就是为处理这类需求而创建的。

foreach /take

scala> val list = List(1,9,5,6,7).foreach(println)
1
9
5
6
7
list: Unit = ()

7)对集合进行分组

val seq1 = Seq(1,2,3,4,5,6,7)  
val res = seq1.partition(_%2==0)  分组

8)Fold
一个流行的操作是 fold。在 Scala 的上下文中,通常可以考虑 foldLeft 和 foldRight。他们是从不同的方面做同样的工作:
fold foldLeft foldRight

scala> val seq2 = Seq(1, 2, 3, 4, 5)
seq2: Seq[Int] = List(1, 2, 3, 4, 5)

scala> seq2.foldLeft(0)(_+_)   //从左边做运算,0当做初始值
res71: Int = 15	

scala> seq2.foldLeft(10)(_-_)
res75: Int = -5

scala> seq2.foldRight(10)(_-_)
res72: Int = -7

第一对括号中,我们放一个起始值。 在第二对括号中,我们定义需要对数字序列的每个元素执行的操作
seq2.foldLeft(0)((res, n)=> res + n)
val words = Seq(“apple”, “dog”, “table”)
words.foldLeft(0)((resultLength, word) => resultLength + word.length)

foldLeft, reduceRight, foldRight

方法foldLeft与reduceLeft工作方法很想,但是它让你指定一个值作为第一个元素。下面这个例子真是了求和算
法,第一个是reduceLeft方法,后面是foldLeft方法,我们来看看它们的区别:

scala> seq2.reduceLeft(_-_)
res76: Int = -13

scala> seq2.reduceRight(_-_)
res77: Int = 3

seq2.reduceLeft(-)
seq2.reduceRight(-)

(1 to 100).foreach(println)
(1 to 100).par.foreach(println) //par并行执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值