Scala基础(一)部署、数据类型及简单语法

概述

官网
在这里插入图片描述

Scala是运行在 JVM 上的多范式编程语言,同时支持面向对象编程(OOP)函数式编程(FP)

官网文档可以看到已经有Scala3,但还是要用Scala2(老版本稳定性好):

在这里插入图片描述

Scala2下载地址

Scala优点:语法简洁、灵活。是静态编程语言(源码→编译[确定数据类型,避免某些bug]→执行,比起Python这种动态编程语言直接 源码→加载执行 安全)。

官网API

菜鸟Scala教程

部署

安装路径不能有中文空格!!!

Win10部署Scala SDK

先安装JDK1.8,配置环境变量。之前配置过就可以略过。

解压到某个文件夹,安装路最好不要有中文和空格!!!之后win+Q搜索环境变量,即可配置环境变量:

SCALA_HOME=C:\soft\scala-2.11.12 
path=%SCALA_HOME%\bin;

在这里插入图片描述
在这里插入图片描述

win+R,输入cmd回车,敲scala(启动Scala解释器)验证是否成功:

在这里插入图片描述

:quit(这个:必须有)可以退出cmd模式的scala。

Linux部署Scala SDK

上传、解压、配置环境变量、shell敲scala验证,流程与Win10部署差不多。

cd /export/software/
rz
tar -zxvf scala-2.11.12.tgz -C /export/server
cd /export/server/
scp -r scala-2.11.12 node2:$PWD
scp -r scala-2.11.12 node3:$PWD
vim /etc/profile

末尾插入:

#SCALA_HOME
export SCALA_HOME=/export/server/scala-2.11.12
export PATH=$PATH:$SCALA_HOME/bin

保存后:

source /etc/profile

敲scala测试是否成功:

[root@node1 server]# scala
Welcome to Scala 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_241).
Type in expressions for evaluation. Or try :help.

scala> print("hello scala")
hello scala
scala> :quit

再配置node2和node3的环境变量并测试,不再赘述。

IDEA部署Scala插件

当然不可能一直用cmd来做Scala,idea更方便些。。。插件中搜索Scala,自动安装的插件和本机兼容性好。

在这里插入图片描述

选Plugins,搜索scala:

在这里插入图片描述

当然安装下载最多的。。。安装完成后点Restart IDE或者手动关闭重启都可以:

在这里插入图片描述

重启后新建个项目:

在这里插入图片描述

简单使用,选Scala空白项目,后期可以使用Maven实现Scala与Java联合编程。

在这里插入图片描述

首次启动没有Scala的SDK,需要点Create:

在这里插入图片描述

如果搜不到,说明环境变量还没有刷新,需要重启计算机才行。中间随便点一下(变蓝)后OK即可点Finish。

在这里插入图片描述

在src中右键→New→Scala Class,就可以创建新的Scala类。当然为了不影响主体,也可以新建module方便测试:

在这里插入图片描述

在这里插入图片描述

选Object后会发生这种事。。。Scala严禁随意使用空格:

在这里插入图片描述

使用psvm当然是不行的,要使用main

在这里插入图片描述

object HelloWorld {
  def main(args: Array[String]): Unit = {
    print("Hello World")
  }
}

首次ctrl+shift+f10运行会很慢:

Hello World
Process finished with exit code 0

编译后发现编译出了.class字节码文件:

在这里插入图片描述

反编译试试:

在这里插入图片描述

不明觉厉,但是可以看出这个class后缀的文件和正常的Java文件差不多,说明Scala是使用JVM的。

语法基础

Scala解释器

学习Scala基本语法可以考虑使用Scala解释器,不需要多余内容,可以像Linux命令一样,一次执行一条代码,马上可以看到结果。比起用idea写类更方便。

定义变量

Scala和Java的语法不太一样。标准套路:

val/var 变量名:变量类型 = 初始值

val定义的是不可重新赋值的变量,var定义的是可以重新赋值的变量。变量名在前,变量类型在后(变量类型可以省略,Scala可以自动推测),末尾不需要;(+;也不会报错,但是没什么用)。

//定义val,自动推测数据类型,数据的值不可修改
scala> val str0001="haha1"
str0001: String = haha1
scala> str0001="haha2"
<console>:12: error: reassignment to val
       str0001="haha2"

//定义var,自动推测数据类型,数据的值可以修改
scala> var str0002="hehe1"
str0002: String = hehe1
scala> str0002="hehe2"
str0002: String = hehe2

//区分大小写
scala> val str0003:String = "0003"
str0003: String = 0003
scala> val str0003:string = "0003"
<console>:11: error: not found: type string
       val str0003:string = "0003"

//没有""双引号包裹值会报错

当某些变量的数据量比较大,且不需要马上加载到JVM内存,就需要惰性赋值,需要的时候才加载到JVM内存。套路:

lazy val 变量名 = 表达式
//惰性赋值只能使用val,不能用var
scala> lazy var SQL1 = "select"
<console>:1: error: lazy not allowed here. Only vals can be lazy
lazy var SQL1 = "select"

//惰性赋值的val可以更改值
scala> val SQL1 = "select"
SQL1: String = select
scala> val SQL1 = "select1"
SQL1: String = select1
scala> SQL1
res1: String = select1

//使用"""三引号修饰字符串,可以换行输入
scala> lazy val SQL2="""
     | SELECT
     |     *
     | FROM
     |     table1;
     | """
SQL2: String = <lazy>
scala> SQL2
res4: String =
"
SELECT
    *
FROM
    table1;
"

Scala中也有类似C#中使用$拼接字符串的方式,但是毕竟不是同一种语言,插值表达式的套路有所不同:

scala> val name = "张三"	//支持中文字符串
name: String = 张三
scala> val age = 20
age: Int = 20

scala> val personinfo = s"name = ${name},age = ${age}"	//插值表达式
personinfo: String = name = 张三,age = 20
scala> println(personinfo)							//输出变量
name = 张三,age = 20
scala> println(s"${personinfo}>>${1+2}"+"haha")		//{}花括号内可以是运算式、对象.方法调用,还可以使用+连接字符串
name = 张三,age = 20>>3haha

数据类型

由于需要使用JVM,基本数据类型与Java的包装类数据类型基本一致。

基础类型类型说明
Byte8位有符号整数
Short16位有符号整数
Int32位有符号整数
Long64位有符号整数
Char16位无符号Unicode字符
StringChar类型的序列(字符串)
Float32位单浮点数
Double64位双浮点数
Boolean布尔,true或者false

Scala所有数据类型都是大写字母开头。一般让Scala自动推测数据类型就好。

在这里插入图片描述

类型说明
Any所有类型的父类
AnyVal所有数值类型的父类
AnyRef所有对象类型(引用数据类型)的父类
Unit表示无值(void),用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()
Nullnull或者空引用
Nothing所有类型的子类(抛出的一次返回值是Nothing)

运算符

类别操作符
算数运算符+、-、*、/
关系运算符>、<、==、!=、>=、<=
逻辑运算符&&、||、!
位运算符&、||、^、<<、>>

Scala中没有++--运算符:

scala> 5
res14: Int = 5

scala> 5++
<console>:12: error: value ++ is not a member of Int
       5++
        ^

scala> 5--
<console>:12: error: value -- is not a member of Int
       5--

Scala使用==!=比较字符串的值是否一致,使用eq方法比较2个对象的引用值:

scala> val str1 = "aaa"
str1: String = aaa

scala> val str2 = str1+""
str2: String = aaa

scala> str1 == str2
res12: Boolean = true		//字符串内容相同

scala> str1.eq(str2)
res13: Boolean = false		//字符串的引用不同

块表达式

Scala也是使用{}花括号来表示一个代码块(代表这一大坨是一个整体)。块表达式有值:

scala> val a={
     | 1+1
     | 3
     | 5
     | }
<console>:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
       1+1
        ^
<console>:13: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
       3
       ^
a: Int = 5

显然块表达式的值就是最后一个表达式的值。如果只有一个表达式,显然{}可以省略。

条件表达式

对应其它语言的if判断的分支结构。Scala有if/else,但是没有三元表达式(可以自己定义方法用if/else实现)。也有类似Java和C#中Switch/Case的功能。

scala> val a=20
a: Int = 20
scala> val b = if(a!=20) 5 else 10	//实现if/else
b: Int = 10

scala> var c = a match {			//需要使用match实现switch/case
     | case 10 => 10
     | case 20 => 21
     | case 30 => 32
     | case _  => 0
     | }
c: Int = 21

if/else可以嵌套多层,也可以多分支,不赘述。

循环表达式

while循环和java相同:

scala> var a = 5
a: Int = 5
scala> while(a>=0) {a=a-1;print(a)}		//使用;分割同一行的语句
43210-1

当然也可以使用while(true)的死循环。。。

for循环的套路则有所不同:

scala> val array1 = Array(11,22,33)
array1: Array[Int] = Array(11, 22, 33)

scala> for( i <- array1) println(i)		//可以遍历数组/集合/表达式
11
22
33

scala> for(i <- 1 to 5) print(i)		//to是包含后边的参数
12345
scala> for(i <- 1 until 5) print(i)		//until是不包含后边的参数
1234
scala> for(i <- 1 to 5 if i%2 != 0) print(i)	//守卫条件
135

scala> val b = for( i <- array1) yield i*10+1	//for推导式
b: Array[Int] = Array(111, 221, 331)

scala> array1.map(_*10+1)				//函数式编程更高效
res24: Array[Int] = Array(111, 221, 331)

可以直接遍历数组/集合/表达式,还可以使用守卫条件for推导式,比Java的for循环强大。

Scala没有BreakContinue关键字,好在提供了Breaks类,可以模拟出相同的效果:

import scala.util.control.Breaks._

object BreakDemo {
  def main(args: Array[String]): Unit = {
    //模拟break
    breakable{
      for (i <- 1 to 10){
        if(i>6) break()
        else print(i)
      }
    }

    println("*****-----华丽的分割线-----*****")

    //模拟continue
    breakable{
      for (i <- 1 to 100){
        if(i%10==0) break()
        else print(i)
      }
    }

  }
}

使用idea比较方便,当然cmd里也可以导包。。。

方法与函数

Java类中封装的一大坨功能模块叫方法(method直译),C和Lua中封装的功能模块叫函数(function直译),貌似区分并不明确。但是Scala中方法和函数有极大的区别。在Scala这种函数式编程语言中,函数是头等公民(极其重要)。

方法

方法定义是这种套路:

def 方法名(变量名1:变量类型=默认值1,变量名2:变量类型=默认值2):返回类型 ={
    //方法体
}

可以省略很多内容:

scala> def method1(a:Int,b:Int)=a+b		//双参数方法
method1: (a: Int, b: Int)Int
scala> method1(1,2)
res3: Int = 3

scala> def method2=print("haha")		//无参方法
method2: Unit
scala> method2
haha

scala> def method3(a:Int)(b:Int)=a+b	//另一种格式的双参数方法
method3: (a: Int)(b: Int)Int
scala> method3(1)(2)
res34: Int = 3

但是递归方法(例如:求阶乘)不能省略:

scala> def method1(a:Int) = if(a<1) 1 else method1(a-1)*a
<console>:13: error: recursive method method1 needs result type
       def method1(a:Int) = if(a<1) 1 else method1(a-1)*a
                                           ^

scala> def method1(a:Int):Int = if(a<1) 1 else method1(a-1)*a
method1: (a: Int)Int

scala> method1(5)
res6: Int = 120

调用无默认值的方法时不给参数会报错:

scala> def method1(a:Int) = if(a<1) 1 else method1(a-1)*a
scala> method1()
<console>:13: error: not enough arguments for method method1: (a: Int)Int.
Unspecified value parameter a.
       method1()

scala> def method1(a:Int=5):Int = if(a<1) 1 else method1(a-1)*a		//给定默认参数
method1: (a: Int)Int

scala> method1()												//不给参数时调用默认参数
res11: Int = 120

带名参数的调用和C语言差不多。

Scala支持变长参数

def 方法名(参数名1:参数类型*):返回类型={
    //方法体
}

事实上可以省略很多内容:

scala> def method1(a:Int*)=a.sum
method1: (a: Int*)Int

scala> def method1(a:Int*)=a.sum
method1: (a: Int*)Int

scala> val array1 = Array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23)
array1: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23)

scala> method1(array1)
<console>:14: error: type mismatch;		//数组与可变参数不匹配
 found   : Array[Int]
 required: Int
       method1(array1)
scala> method1(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23)
res14: Int = 276

scala> method1(5)
res1: Int = 5

scala> method1{5}					//只有1个参数时可以使用{}花括号调用
res2: Int = 5

scala> method1{1,5}					//不止1个参数时不可以使用{}花括号调用
<console>:1: error: ';' expected but ',' found.
method1{1,5}

方法调用

OOP中常用的就是对象.方法(参数),这种是后缀调用。但是Scala还可以使用对象 方法 参数,这种是中缀调用

scala> var a:Int=1
a: Int = 1

scala> a.to(10)							//后缀调用
res15: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> a to (10)						//中缀调用
res16: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

方法的操作符

scala> val str1 = "haha"
str1: String = haha

scala> val str2 = "hehe"
str2: String = hehe

scala> str1+str2
res40: String = hahahehe

scala> str1 +:str2
res37: scala.collection.immutable.IndexedSeq[Any] = Vector(haha, h, e, h, e)

scala> str1 :+str2
res39: scala.collection.immutable.IndexedSeq[Any] = Vector(h, a, h, a, hehe)

函数

函数的本质都是对象,都是FunctionN的实例(N是函数传入参数的个数)。

scala> new function							//要按Tab才会显示,默认最多22个参数
            Function10   Function14   Function18   Function21   Function5   Function9
Function    Function11   Function15   Function19   Function22   Function6   FunctionalInterface
Function0   Function12   Function16   Function2    Function3    Function7   PartialFunction
Function1   Function13   Function17   Function20   Function4    Function8

scala> def method1(a:Int,b:Int)=a+b				//有def的是方法
method1: (a: Int, b: Int)Int					//显示这是个方法

scala> method1(1,2)
res3: Int = 3

scala> val function1 = (a:Int,b:Int)=>a+b		//无def是函数
function1: (Int, Int) => Int = <function2>		//显示这是2个参数的函数

scala> function1(1,2)
res0: Int = 3

scala> def method2(p:(Int,Int)=>Int)
     | =p(1,2)
method2: (p: (Int, Int) => Int)Int
scala> method2(function1)					//function1是函数,作为参数传给method2
res2: Int = 3

scala> val function2 = (x:Int) =>x +3
function2: Int => Int = <function1>

scala> method2(function2)					//类型不同,不能作为参数传递
<console>:14: error: type mismatch;
 found   : Int => Int
 required: (Int, Int) => Int
       method2(function2)

scala> val array1 = Array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23)
array1: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23)

scala> array1.map(function2)
res4: Array[Int] = Array(4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)

scala> array1.map((x:Int) =>x*5)		//使用匿名函数调用,省去了函数命名的过程
res5: Array[Int] = Array(5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115)

scala> array1.map(_*5)					//使用_一步升天
res6: Array[Int] = Array(5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115)

函数可以作为变量传给方法,方法能够转换成函数(函数不能转换为方法):

scala> def method1(p:(Int,Int)=>Int)=p(1,2)
method1: (p: (Int, Int) => Int)Int

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

scala> method2_									//方法需要空格隔开再+_才能转换成功
<console>:12: error: not found: value method2_
       method2_

scala> method2 _								//方法 _:方法→函数
res9: (Int, Int) => Int = <function2>

scala> method1(method2 _)						//转换后的函数作为参数传递给方法(显式转换)
res10: Int = 3

scala> method1(method2)							//转换后的函数作为参数传递给方法(隐式转换)
res11: Int = 3

数组

Scala中,数组分为

  • 定长数组Array(数组长度不可变,元素可变)
  • 变长数组ArrayBuffer(数组长度可变,元素可变)

定长数组Array

scala> val array1 = new Array[Int](4)								//没有初始值时需要new
array1: Array[Int] = Array(0, 0, 0, 0)

scala> array1
res0: Array[Int] = Array(0, 0, 0, 0)

scala> array1[0]													//Scala中不是通过[]访问
<console>:1: error: identifier expected but integer literal found.
array1[0]
       ^

scala> array[1]														//Scala中不是通过[]访问
<console>:1: error: identifier expected but integer literal found.
array[1]

scala> array1(0)													//Scala中通过()访问
res2: Int = 0

scala> array1(0)=11

scala> array1
res4: Array[Int] = Array(11, 0, 0, 0)

scala> val array2 = Array(1,2,3)									//有初始值时不需要new
array2: Array[Int] = Array(1, 2, 3)

变长数组ArrayBuffer

scala> :quit														//先退出重开命令行

C:\Users\killer>scala
Welcome to Scala 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_241).
Type in expressions for evaluation. Or try :help.

scala> val AB1 = new ArrayBuffer[String]()							//不导包会报错
<console>:11: error: not found: type ArrayBuffer
       val AB1 = new ArrayBuffer[String]()

scala> import scala.collection.mutable.ArrayBuffer					//变长数组使用前需要导包
import scala.collection.mutable.ArrayBuffer

scala> val AB1 = new ArrayBuffer[String]()							//没有初值需要new
AB1: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer()

scala> val AB2 = ArrayBuffer("haha","hehe")							//有初值不需要new
AB2: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(haha, hehe)

scala> AB2(1)													//也是通过()访问,不是[]访问
res0: String = hehe

scala> AB2 += "a1"												//+=是追加内容
res1: AB2.type = ArrayBuffer(haha, hehe, a1)

scala> AB2 + "a2"												//+会变成字符串
res2: String = ArrayBuffer(haha, hehe, a1)a2

scala> AB2.append("a2")											//append和+=都是末尾追加

scala> AB2
res4: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(haha, hehe, a1, a2)

scala> AB2 +="a1"												//可重复添加相同内容
res6: AB2.type = ArrayBuffer(haha, hehe, a1, a2, a1)

scala> AB2 +="a2"
res7: AB2.type = ArrayBuffer(haha, hehe, a1, a2, a1, a2)

scala> AB2 -="a1"												//-=只会去除第一个该内容的元素
res8: AB2.type = ArrayBuffer(haha, hehe, a2, a1, a2)

scala> AB2.remove("a2")											//不能按内容移除
<console>:14: error: type mismatch;
 found   : String("a2")
 required: Int
       AB2.remove("a2")
                  ^

scala> AB2.remove(4)											//可以按照脚标移除
res10: String = a2

scala> AB2														//直接遍历
res11: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(haha, hehe, a2, a1)

scala> for(i <- AB2 ) println(i)								//for直接遍历
haha
hehe
a2
a1

scala> AB2 ++= Array("hive", "sqoop")								//使用++=来追加数组的内容
res13: AB2.type = ArrayBuffer(haha, hehe, a2, a1, hive, sqoop)

scala> for (i <- 0 to AB2.length-1) print(AB2(i)+" ")				//for使用角标遍历
haha hehe a2 a1 hive sqoop
scala> for (i <- 0 to AB2.length) print(AB2(i)+" ")					//也会越界
haha hehe a2 a1 hive sqoop java.lang.IndexOutOfBoundsException: 6
  at scala.collection.mutable.ResizableArray$class.apply(ResizableArray.scala:43)
  at scala.collection.mutable.ArrayBuffer.apply(ArrayBuffer.scala:48)
  at $anonfun$1.apply$mcVI$sp(<console>:14)
  at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:160)
  ... 32 elided

scala> for (i <- 0 until AB2.length) print(AB2(i)+" ")				//for使用脚标遍历
haha hehe a2 a1 hive sqoop

数组常用算法

自带了多种算法,例如:升序排序sorted、反转数组reverse、累加sum、最大值max、最小值min

scala> AB2.sorted													//String类型的可变长数组也可以排序
res18: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(a1, a2, haha, hehe, hive, sqoop)

scala> AB2.sorted.reverse											//反转数组,链式编程
res19: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(sqoop, hive, hehe, haha, a2, a1)

scala> val array1 = Array(1,2,3,4,5,6)
array1: Array[Int] = Array(1, 2, 3, 4, 5, 6)

scala> array1.sum													//累加
res25: Int = 21

scala> array1.max													//求最大值
res26: Int = 6

scala> array1.min													//求最小值
res27: Int = 1

scala> array1.reverse												//反转数组
res29: Array[Int] = Array(6, 5, 4, 3, 2, 1)

scala> array1.reverse.sorted										//升序排序,链式编程
res30: Array[Int] = Array(1, 2, 3, 4, 5, 6)

迭代访问数组

Scala为多种集合预置了迭代器iterator,用于迭代访问集合。以数组为例:

scala> :quit

C:\Users\killer>scala									//重启Scala命令行
Welcome to Scala 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_241).
Type in expressions for evaluation. Or try :help.

scala> val array1 = Array(11,12,13)
array1: Array[Int] = Array(11, 12, 13)

scala> val i1 = array1.iterator							//为数组构建迭代器对象
i1: Iterator[Int] = non-empty iterator

scala> while(i1.hasNext) {println(i1);println(i1.next)}		//迭代数组
non-empty iterator										//迭代过程中不断指向下一个,迭代器非空
11
non-empty iterator
12
non-empty iterator
13

scala> i1												//迭代结束后迭代器清空
res2: Iterator[Int] = empty iterator

scala> i1.next											//迭代器没有下一个元素时强行读取下一个会报错(指针越界)
java.util.NoSuchElementException: next on empty iterator
  at scala.collection.Iterator$$anon$2.next(Iterator.scala:39)
  at scala.collection.Iterator$$anon$2.next(Iterator.scala:37)
  at scala.collection.IndexedSeqLike$Elements.next(IndexedSeqLike.scala:63)
  ... 32 elided

元组

使用()把不同数据类型的数据聚集起来就是元组,类似C语言的结构体。当然元组中也可以有相同数据类型的数据。。。Scala内置了22个Tuple对象:

scala> :quit

C:\Users\killer>scala
Welcome to Scala 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_241).
Type in expressions for evaluation. Or try :help.

scala> new Tuple			//要按Tab键才会出现
Tuple1    Tuple11   Tuple13   Tuple15   Tuple17   Tuple19   Tuple20   Tuple22   Tuple4   Tuple6   Tuple8
Tuple10   Tuple12   Tuple14   Tuple16   Tuple18   Tuple2    Tuple21   Tuple3    Tuple5   Tuple7   Tuple9

只有2个元素的就是对偶元组

scala> val tuple1 = (11,"haha")			//新建对偶元组
tuple1: (Int, String) = (11,haha)

scala> tuple1.swap						//交换对偶元组的2个元素
res2: (String, Int) = (haha,11)

scala> tuple1							//swap交换不改变原先对偶元组的内容
res3: (Int, String) = (11,haha)

一般使用的不是对偶元组:

scala> val tuple2 = (1,1.2,true,"haha")				//给定初始值创建
tuple2: (Int, Double, Boolean, String) = (1,1.2,true,haha)

scala> val tuple3 = new Tuple4(2,2.2,false,"hehe")	//使用new创建
tuple3: (Int, Double, Boolean, String) = (2,2.2,false,hehe)

scala> tuple2._2								//使用._数字(从1开始)的方式访问
res9: Double = 1.2

scala> for(i <- tuple2)							//不能使用for遍历元组
     | print(i)
<console>:13: error: value foreach is not a member of (Int, Double, Boolean, String)
       for(i <- tuple2)

scala> tuple2.productIterator.foreach(println)		//可以使用Tab补全。需要变成迭代器才能遍历
1
1.2
true
haha

列表

可重复列表List

分为不可变的List可变的ListBuffer

scala> val list1=List(11,22,33,44,55)				//不导包默认为不可变的List
list1: List[Int] = List(11, 22, 33, 44, 55)

scala> import scala.collection.mutable.ListBuffer	//导包
import scala.collection.mutable.ListBuffer

scala> val list2=ListBuffer(66,77,88,99)			//导包后可以用可变的ListBuffer
list2: scala.collection.mutable.ListBuffer[Int] = ListBuffer(66, 77, 88, 99)

scala> val list3 = 11::22::33						//使用::追加的方式构建列表,这种情况会报错(∵不能自动推测类型)
<console>:12: error: value :: is not a member of Int
       val list3 = 11::22::33

scala> val list3 = 11::22::33::Nil					//使用::追加的方式构建列表,末尾必须是Nil
list3: List[Int] = List(11, 22, 33)

scala> val list4=Nil								//构建空的List
list4: scala.collection.immutable.Nil.type = List()

scala> list1.head									//查看首个元素
res0: Int = 11

scala> list1.tail									//查看去头元素(除首个元素外的其余元素)
res1: List[Int] = List(22, 33, 44, 55)

scala> list1 :+101									//可以:+在末尾追加元素
res9: List[Int] = List(11, 22, 33, 44, 55, 101)

scala> list1										//上述操作不影响原list
res10: List[Int] = List(11, 22, 33, 44, 55)

scala> list1(0)										//按脚标获取数据(从0开始)
res27: Int = 11

scala> list1(0)=1									//不能修改不可变List的元素
<console>:14: error: value update is not a member of List[Int]
       list1(0)=1

scala> list1 +=101									//表达式不转换为赋值,因为接收方不可赋值。
<console>:14: error: value += is not a member of List[Int]
  Expression does not convert to assignment because receiver is not assignable.
       list1 +=101

scala> list1.:+(101)								//使用.:+后缀调用的方式追加元素
res16: List[Int] = List(11, 22, 33, 44, 55, 101)

scala> list1										//不影响原List
res17: List[Int] = List(11, 22, 33, 44, 55)

scala> list1 +:102									//前方追加元素不能识别数据类型
<console>:14: error: value +: is not a member of Int
       list1 +:102
             ^

scala> list1.+:102									//使用.+:后缀调用的方式也不能识别数据类型
<console>:1: error: ';' expected but integer literal found.
list1.+:102
        ^

scala> list1.+:(102)								//数据()小括号括起来就可以识别数据类型
res19: List[Int] = List(102, 11, 22, 33, 44, 55)

scala> list1.::(102)								//::和+:同样是在头部追加元素
res21: List[Int] = List(102, 11, 22, 33, 44, 55)

scala> list2(0)=61									//可变列表ListBuffer可以通过脚标修改元素

scala> list2
res32: scala.collection.mutable.ListBuffer[Int] = ListBuffer(61, 77, 88, 99)

scala> list2+=101									//可变列表可以直接追加并覆盖原列表
res35: list2.type = ListBuffer(61, 77, 88, 99, 101)

scala> list2 +=(102)								//尾部追加时没有()也可以识别
res36: list2.type = ListBuffer(61, 77, 88, 99, 101, 102)

scala> list2 +=101									//列表可以有重复的元素
res37: list2.type = ListBuffer(61, 77, 88, 99, 101, 102, 101)

scala> list2 -=101									//使用-只会移除首个该内容的元素
res38: list2.type = ListBuffer(61, 77, 88, 99, 102, 101)

scala> list3.to										//使用Tab补全,可以查看更多方法
to        toBuffer       toIterable   toList   toParArray   toSet      toString        toVector
toArray   toIndexedSeq   toIterator   toMap    toSeq        toStream   toTraversable

scala> list3.toArray								//可以转换为Array数组
res39: Array[Int] = Array(11, 22, 33)

scala> list3.toList									//可以转换为不可变列表List(没什么用。。。自己本身就是List)
res41: List[Int] = List(11, 22, 33)

scala> list2.to										//可变与不可变列表的转换方法相同
to        toBuffer       toIterable   toList   toParArray   toSet      toString        toVector
toArray   toIndexedSeq   toIterator   toMap    toSeq        toStream   toTraversable

还有很多方法,例如:压平、∩、∪。。。用的时候慢慢查。。。或者参照API。

不可重复列表Set

Set是无序不可重复的列表,主要用于去重,但是又会导致数据无序。。。同样是有可变Set不可变Set

scala> :quit													//重启scala命令行

C:\Users\killer>scala
Welcome to Scala 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_241).
Type in expressions for evaluation. Or try :help.

scala> val set1 = Set(1,3,2,1,3,4,3,2,1,5)							//自动去重
set1: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)

scala> import scala.collection.mutable.Set
import scala.collection.mutable.Set

scala> val set2 = Set(1,3,2,1,3,4,3,2,1,5)							//自动去重
set2: scala.collection.mutable.Set[Int] = Set(1, 5, 2, 3, 4)

scala> set1+=6													//不可变Set不能修改元素
<console>:14: error: value += is not a member of scala.collection.immutable.Set[Int]
  Expression does not convert to assignment because receiver is not assignable.
       set1+=6
         ^

scala> set2 +=6													//可变Set可以修改元素
res2: set2.type = Set(1, 5, 2, 6, 3, 4)

scala> set2 -=6
res3: set2.type = Set(1, 5, 2, 3, 4)

映射Map

Scala中Map分为可变Map不可变Map(长度不可改变,元素也不可改变)。和其它类型不同,可变与不可变都叫map,一字不差。。。想区分只能看有木有导包(不导包默认是不可变map,导包后可以使用可变map)。

定义Map按照这种套路:

val/var map = Map(->,->,->...) 					//键→值的键值对可读性更好
val/var map = Map((,), (,), (,), (,)...)

用起来还是比较简单的:

scala> :quit

C:\Users\killer>scala										//重启scala命令行
Welcome to Scala 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_241).
Type in expressions for evaluation. Or try :help.

scala> val map1 = Map("name" -> "张三","age"->"13")			//导包前为不可变Map
map1: scala.collection.immutable.Map[String,String] = Map(name -> 张三, age -> 13)

scala> val map2 = Map(("name","张三"),("age",23))
map2: scala.collection.immutable.Map[String,Any] = Map(name -> 张三, age -> 23)

scala> import scala.collection.mutable.Map					//导包
import scala.collection.mutable.Map

scala> val map3 = Map("name" -> "张三","age"->"33")			//导包后变为可变Map
map3: scala.collection.mutable.Map[String,String] = Map(age -> 33, name -> 张三)

scala> val map4 = Map(("name","张三"),("age",43))
map4: scala.collection.mutable.Map[String,Any] = Map(age -> 43, name -> 张三)

scala> map1												//可以直接看到键值对
res4: scala.collection.immutable.Map[String,String] = Map(name -> 张三, age -> 13)

scala> map1("name")										//可以根据键查看值
res5: String = 张三

scala> map1("name")="lisi"								//不能修改不可变Map的数据
<console>:14: error: value update is not a member of scala.collection.immutable.Map[String,String]
       map1("name")="lisi"
       ^

scala> map1 +=("name"->"lisi")							//不能修改不可变Map的数据
<console>:14: error: value += is not a member of scala.collection.immutable.Map[String,String]
  Expression does not convert to assignment because receiver is not assignable.
       map1 +=("name"->"lisi")

scala> map3("name")="lisi"								//可以修改可变Map的数据

scala> map3
res7: scala.collection.mutable.Map[String,String] = Map(age -> 33, name -> lisi)

scala> map1("nama")										//会报错
java.util.NoSuchElementException: key not found: nama
  at scala.collection.MapLike$class.default(MapLike.scala:228)
  at scala.collection.AbstractMap.default(Map.scala:59)
  at scala.collection.MapLike$class.apply(MapLike.scala:141)
  at scala.collection.AbstractMap.apply(Map.scala:59)
  ... 32 elided

scala> map1.get("nama")									//key不存在也不报错
res10: Option[String] = None

scala> map1.get("name")									//相对安全。返回Option类型
res8: Option[String] = Some(张三)

scala> map3 +=("university"->"上兰村帝国技校")				//可追加键值对
res11: map3.type = Map(age -> 33, name -> lisi, university -> 上兰村帝国技校)

scala> map3
res12: scala.collection.mutable.Map[String,String] = Map(age -> 33, name -> lisi, university -> 上兰村帝国技校)

scala> map3 +=(("k1","v1"),("k2","v2"))					//可追加键值对
res13: map3.type = Map(k2 -> v2, k1 -> v1, age -> 33, name -> lisi, university -> 上兰村帝国技校)

scala> map3
res14: scala.collection.mutable.Map[String,String] = Map(k2 -> v2, k1 -> v1, age -> 33, name -> lisi, university -> 上兰村帝国技校)

scala> map3 +=(("k3","v3"),("k4","v4"),("k5","v5"))		//说明键值对无序排列
res15: map3.type = Map(k2 -> v2, k5 -> v5, k4 -> v4, k1 -> v1, age -> 33, name -> lisi, k3 -> v3, university -> 上兰村帝国技校)

scala> map3
res16: scala.collection.mutable.Map[String,String] = Map(k2 -> v2, k5 -> v5, k4 -> v4, k1 -> v1, age -> 33, name -> lisi, k3 -> v3, university -> 上兰村帝国技校)

scala> for(i<- map3) println(i+";")					//遍历Map
(k2,v2);
(k5,v5);
(k4,v4);
(k1,v1);
(age,33);
(name,lisi);
(k3,v3);
(university,上兰村帝国技校);

scala> map3.keys								//返回Map中所有key并返回个set集合
res18: Iterable[String] = Set(k2, k5, k4, k1, age, name, k3, university)

scala> for(k <- map3.keys) println(s"${k}:${map3(k)}")
k2:v2
k5:v5
k4:v4
k1:v1
age:33
name:lisi
k3:v3
university:上兰村帝国技校

scala> for((k,v) <- map3) println(s"${v}<---${k}")	//使用模式匹配遍历
v2<---k2
v5<---k5
v4<---k4
v1<---k1
33<---age
lisi<---name
v3<---k3
上兰村帝国技校<---university
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值