Scala语法(一) 基础语法(变量&常量&判断&循环&数组&集合)

一时失言乱红尘 2022-02-13 17:45 394阅读 0赞

前言

在前面的章节中, 我们介绍了如何在Eclipse内安装Scala环境. 本章开始, 我们将讲解下Scala的基本语法.

PS: 1. 个人虽然没有想转Scala语言开发的思想, 但是近来Scala语言被各种媒体炒的火热. 了解下总没有坏处. 就个人而言, 还是非常喜欢Java的简洁语法的.

  1. 另在学习过程中, Scala经常会去调用Java的语法. 个人感觉, Scala在某些方面做的仍然还没有到位和完全. 但是, 对于Spark等的大数据开发, Scala或许是一门不错的语言.
  2. Eclipse中的Scala IDE(Oxygen)做的仍然不是非常完善. 最需要的查看Scala内的源码的功能缺失, 后期Scala的开发可能会转向使用IDEA进行开发.(虽然, 个人非常不喜欢IDEA那些花里胡哨的所谓自动化功能.)
  3. 本文所涉及的代码, 都可以在我的github项目的https://github.com/SeanYanxml/arsenal 的 arsenal-scala/quick-scala下找到.

前置准备

Eclipse Scala环境的配置 根据上述的文章配置好相关的开发环境. (IDEA略过此步骤)

Maven的Pom.xml文件依赖. 由于之前的Maven创建模板内, Scala的某些依赖的版本号已经不适合个人使用的版本. 个人将其替换成了相应的版本. 读者可以根据个人需要, 从 https://mvnrepository.com/ 上查询并选择需要的版本.

  1. <project xmlns="http://maven.apache.org/POM/4.0.0"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>com.yanxml</groupId>
  6. <artifactId>quick-scala</artifactId>
  7. <version>0.0.1-SNAPSHOT</version>
  8. <name>${project.artifactId}</name>
  9. <description>My wonderfull scala app</description>
  10. <inceptionYear>2010</inceptionYear>
  11. <licenses>
  12. <license>
  13. <name>My License</name>
  14. <url>http://....</url>
  15. <distribution>repo</distribution>
  16. </license>
  17. </licenses>
  18. <properties>
  19. <maven.compiler.source>1.8</maven.compiler.source>
  20. <maven.compiler.target>1.8</maven.compiler.target>
  21. <encoding>UTF-8</encoding>
  22. <scala.tools.version>2.11</scala.tools.version>
  23. <scala.version>2.11.8</scala.version>
  24. </properties>
  25. <dependencies>
  26. <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
  27. <dependency>
  28. <groupId>org.apache.commons</groupId>
  29. <artifactId>commons-lang3</artifactId>
  30. <version>3.7</version>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.scala-lang</groupId>
  34. <artifactId>scala-library</artifactId>
  35. <version>${scala.version}</version>
  36. </dependency>
  37. <dependency>
  38. <groupId>org.scala-lang</groupId>
  39. <artifactId>scala-library</artifactId>
  40. <version>2.11.8</version>
  41. </dependency>
  42. <dependency>
  43. <groupId>org.scala-lang</groupId>
  44. <artifactId>scala-compiler</artifactId>
  45. <version>2.11.8</version>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.scala-lang</groupId>
  49. <artifactId>scala-reflect</artifactId>
  50. <version>2.11.8</version>
  51. </dependency>
  52. <!-- https://mvnrepository.com/artifact/org.scala-lang/scala-actors -->
  53. <dependency>
  54. <groupId>org.scala-lang</groupId>
  55. <artifactId>scala-actors</artifactId>
  56. <version>2.11.8</version>
  57. </dependency>
  58. <!-- Test -->
  59. <dependency>
  60. <groupId>junit</groupId>
  61. <artifactId>junit</artifactId>
  62. <version>4.11</version>
  63. <scope>test</scope>
  64. </dependency>
  65. <!-- <dependency> <groupId>org.specs2</groupId> <artifactId>specs2_${scala.tools.version}</artifactId>
  66. <version>3.0</version> <scope>test</scope> </dependency> -->
  67. <!-- https://mvnrepository.com/artifact/org.scalatest/scalatest -->
  68. <dependency>
  69. <groupId>org.scalatest</groupId>
  70. <artifactId>scalatest_2.11</artifactId>
  71. <version>3.0.0-M16-SNAP6</version>
  72. <scope>test</scope>
  73. </dependency>
  74. <dependency>
  75. <groupId>org.scalatest</groupId>
  76. <artifactId>scalatest_${scala.tools.version}</artifactId>
  77. <version>3.0.0-M16-SNAP6</version>
  78. <scope>test</scope>
  79. </dependency>
  80. <!-- spark -->
  81. <dependency>
  82. <groupId>org.apache.spark</groupId>
  83. <artifactId>spark-core_2.11</artifactId>
  84. <version>2.2.1</version>
  85. </dependency>
  86. <!-- akka -->
  87. <!-- https://mvnrepository.com/artifact/com.typesafe.akka/akka-actor -->
  88. <dependency>
  89. <groupId>com.typesafe.akka</groupId>
  90. <artifactId>akka-actor_2.11</artifactId>
  91. <version>2.3.14</version>
  92. </dependency>
  93. <!-- https://mvnrepository.com/artifact/com.typesafe.akka/akka-remote -->
  94. <dependency>
  95. <groupId>com.typesafe.akka</groupId>
  96. <artifactId>akka-remote_2.11</artifactId>
  97. <version>2.3.14</version>
  98. </dependency>
  99. </dependencies>
  100. <build>
  101. <sourceDirectory>src/main/scala</sourceDirectory>
  102. <testSourceDirectory>src/test/scala</testSourceDirectory>
  103. <plugins>
  104. <plugin>
  105. <!-- see http://davidb.github.com/scala-maven-plugin -->
  106. <groupId>net.alchim31.maven</groupId>
  107. <artifactId>scala-maven-plugin</artifactId>
  108. <version>3.1.3</version>
  109. <executions>
  110. <execution>
  111. <goals>
  112. <goal>compile</goal>
  113. <goal>testCompile</goal>
  114. </goals>
  115. <configuration>
  116. <args>
  117. <arg>-make:transitive</arg>
  118. <arg>-dependencyfile</arg>
  119. <arg>${project.build.directory}/.scala_dependencies</arg>
  120. </args>
  121. </configuration>
  122. </execution>
  123. </executions>
  124. </plugin>
  125. <plugin>
  126. <groupId>org.apache.maven.plugins</groupId>
  127. <artifactId>maven-surefire-plugin</artifactId>
  128. <version>2.13</version>
  129. <configuration>
  130. <useFile>false</useFile>
  131. <disableXmlReport>true</disableXmlReport>
  132. <!-- If you have classpath issue like NoDefClassError,... -->
  133. <!-- useManifestOnlyJar>false</useManifestOnlyJar -->
  134. <includes>
  135. <include>**/*Test.*</include>
  136. <include>**/*Suite.*</include>
  137. </includes>
  138. </configuration>
  139. </plugin>
  140. </plugins>
  141. </build>
  142. </project>

正文

从本节开始, 我们正式介绍Scala的语法.

本章主要介绍如下几个方面:

  • QuickStart - HelloWorld
  • 常量&变量
  • 判断(if)
  • 循环(while/for/map)
  • 数组(Array)
  • 元组(Tuple)
  • 集合(Map&List&Set)
HelloWorld

在进行学习之前, 先使用HelloWorld小程序判断当前的编译器环境是否配置完毕.

在Scala中, 主要有2种方式创建静态的Main方法. def main&extends scala.APP.

另外值得一提的是, 这边使用的是object的前缀, 千万不要使用class前缀. 这是初学者非常容易犯的错误.(笔者当初就因为这个问题, 以为是IDE环境的问题, 绕了好久. 希望各位引以为戒.)

  1. object App {
  2. def main(args : Array[String]) {
  3. println( "Hello World!" )
  4. }
  5. }
  6. object HelloWorld extends App{
  7. println("HelloWorld")
  8. }
常量&变量

在Scala中, 与Java一样. 也有8种基本数据类型, 但是不存在向Java内的那么复杂. 即不存在基础类与封装类(int & Integer)的区别. 而是统一的使用基础类.(Byte Short Int Long Float Double Char Boolean)

常量的定义使用val关键字, 变量的定义使用var关键字. 在定义的过程中, 可以直接指定变量&常量的数据类型, 也可以不进行指定, 由系统自动识别装配.(var hello = "123"/ var hello2:String = "hello")

  1. @Test
  2. // 常见的变量与常量类型
  3. def variable(){
  4. // 常量
  5. // 使用val修饰的变量值是不可变的,相当于java里用final修饰的变量.
  6. val a = 1
  7. // false. val can not change.
  8. // a = 2
  9. // 变量
  10. // < var a = xx >. scala会自动推断变量的类型.
  11. // < var a : type(Int,String,...) >. 可以通过值得scala变量的类型.
  12. var b1 = 1
  13. var b2: String = "hello"
  14. }
判断(if)

Scala内的if判断与Java中的类似. 但是表达式更加的泛化, 并且可以直接赋值给变量. 并且if内的返回值可以是多种数据类型的.(详间下方Scala示例.)

  1. # Java
  2. int a=0;
  3. if(a>0){
  4. a++;
  5. }else{
  6. a--;
  7. }
  8. # Scala
  9. def ifelse(){
  10. println("if---else---test")
  11. val x = 1
  12. // 判断x的值 返回值给y
  13. val y = if(x>0) 1 else -1
  14. println(y)
  15. // 支持混合类型表达式
  16. val z = if(x>2) 1 else "error"
  17. println(z)
  18. // 缺失else 相当于if(x>2) else()
  19. val m = if(x>2) 1
  20. println(m)
  21. // scala中有个Unit类, 相当于Java中的void.
  22. val n = if(x>2) 1 else()
  23. println(n)
  24. val k = if(x<0) 0 else if(x>2) 1 else -1
  25. println(k)
  26. }
代码块(Block)

Java中, 代码块是由{}中的代码体. 在Scala内也是如此. 唯一不同的是, Scala内的代码体是可以赋值的.

  1. # Java
  2. public static void main(String[]args){
  3. int a=0;
  4. int b=0;
  5. }
  6. # Scala
  7. @Test
  8. // 块表达式(如何确定block的返回值?)
  9. def block(){
  10. println("block---test")
  11. val x = 0
  12. val result = {
  13. if (x>0) -1 else 1
  14. }
  15. println(result)
  16. }
循环(For&While)

在Java内, 我们经常使用while/do-while/for三种循环体. 在Scala内, 我们也可以使用. 但是Scala中, 更经常使用formap()函数进行循环操作.

  1. # java
  2. public static void main(String []args){
  3. int a=2;
  4. while(a>0){
  5. a++;
  6. }
  7. do{
  8. a++;
  9. }while(a>0)
  10. for(int i=a;i>0;i++){
  11. a++;
  12. }
  13. }
  14. # Scala
  15. @Test
  16. // 常见的for循环
  17. def forcycle(){
  18. println("for---cycle---test")
  19. // 遍历 to 是一个方法
  20. 1 to 10
  21. for(i <- 1 to 10){print(i)}
  22. println()
  23. // 数组的定义 (相当于使用数组的Object方法 也就是静态方法)
  24. val arr = Array("a","b","c")
  25. for(a<-arr){print(a)}
  26. println()
  27. // 循环带条件, 主要if判断前没有分号
  28. for(i<- 1 to 3; j<- 1 to 3 if i !=j){
  29. print(10*(i)+j+" ")
  30. }
  31. println()
  32. //for推导式: for的循环的循环体以yield开始, 该循环会构建出一个集合
  33. // 每次迭代生成集合的一个值
  34. val v = for(i<-1 to 10) yield i *10
  35. println(v)
  36. 1.to(10).map(_*10)
  37. // 遍历数组
  38. val arr2 = Array(1,2,3)
  39. val t = for(i<-arr2) yield i*2
  40. println(t)
  41. // 偶数 奇数获取
  42. val arrTmp = Array(1,2,3,4,5,6,7,8)
  43. val arrResult = for(i<-arrTmp){if(i%2==0) i else()}
  44. val arrResult2 = for(i<-arrTmp ; if(i%2==0)) yield i
  45. val arrResult3 = for(i<-arrTmp ; if(i%2==0)) i
  46. val arrResult4 = arrTmp.filter(_%2==0)
  47. for(i <- 1 to arrTmp.length) print(arrTmp(i))
  48. for(i <- 0 until arrTmp.length) println(arrTmp(i))
  49. }

Scala do…while 循环

数组&元组

Scala内的数组与Java内数组的定义略有不同. 且插入和删除操作也非常不一样. Scala内通过+-来进行末尾增加和删除单个元素; ++来增加集合元素. 当然也可以通过insert()remove()函数进行插入和删除多个元素.

  1. #Java
  2. public static void main(String []args){
  3. String []array1= {"1","2","3"};
  4. String []array2 = new String[10];
  5. // 循环遍历1
  6. for(String str:array2){
  7. }
  8. // 循环遍历2
  9. for(int i=0;i<array2.length;i++){
  10. }
  11. }
  12. # Scala
  13. @Test
  14. def initArray(){
  15. // Test1
  16. // 初始化一个长度为8的定长数组, 所有元素均为0
  17. val array1 = new Array[Int](10)
  18. // 直接打印定长数组, 内容为数组的hashcode值
  19. println(array1)
  20. // 将数组转换为缓冲, 可以看到数组内的内容
  21. // to buffer 将数组转换为缓冲
  22. println(array1.toBuffer)
  23. // Test2
  24. // 使用静态方法创建
  25. val array2 = Array[Int](10)
  26. println(array2.toBuffer)
  27. // Test3
  28. val array3 = Array("Hadoop","Strom","Spark")
  29. println(array3(1))
  30. // 变长数组
  31. // 如果想使用数组缓冲,需要导入 import scala.collection.mutable.ArrayBuffer包
  32. val arrayBuffer1 = ArrayBuffer[Int]()
  33. // 尾部追加一个元素 +=尾部追加元素
  34. arrayBuffer1 += 1
  35. // 尾部追加多个元素
  36. arrayBuffer1 += (2,3,4,5)
  37. // 追加一个数组 ++=
  38. arrayBuffer1 ++= Array(6,7)
  39. // 追加一个缓冲数组 ++=
  40. arrayBuffer1 ++= ArrayBuffer(8,9)
  41. // 打印缓冲
  42. println(arrayBuffer1)
  43. // 指定位置添加元素
  44. val arrayBuffer2 = ArrayBuffer[Int]()
  45. arrayBuffer2 += (1,2,3)
  46. // 在数组角标为0的位置 开始插入2个元素
  47. arrayBuffer2.insert(0, -1,0)
  48. // 在数组角标位置为8的位置删除2个雅俗
  49. arrayBuffer2.remove(1,2)
  50. }
  51. /**
  52. * 遍历数组的方式主要有2种
  53. * 1. for循环
  54. * 2. 使用until生成角标, 0 until 10 (包含0不包含10 前封后开)
  55. * 3. map方法
  56. * */
  57. @Test
  58. def foreachArray(){
  59. // 初始化
  60. val array = Array(1,2,3,4,5,6)
  61. // 使用for循环
  62. for(i <- array){
  63. print(i)
  64. }
  65. // 使用角标 (有时候需要获取数组的下标)
  66. // .reverse可以将其进行反转
  67. for(i<-(0 until array.length)){
  68. print(array(i))
  69. }
  70. // 倒转遍历数组
  71. for(i<-(0 until array.length).reverse){
  72. }
  73. // map方式
  74. // 方法转换为一个函数
  75. array.map(println(_))
  76. }
  77. /**
  78. * 转换数组, 生成一个新的数组
  79. * 1. yield方式
  80. * 2. map方法.
  81. * */
  82. @Test
  83. def swapArray(){
  84. val array = Array(1,2,3,4,5)
  85. // 偶数取出来 乘以10
  86. val arrayOdd = for(i<- array;if i%2==0)yield i*10
  87. println(arrayOdd.toBuffer)
  88. // map 方式的隐式函数 (一步一步的简化方式)
  89. array.map((x:Int)=>x*10)
  90. array.map(x=>x*10)
  91. array.map(_*10)
  92. val arrayOddMap = array.filter(_%2==0).map(_*10)
  93. println(arrayOddMap.toBuffer)
  94. }
  95. /**
  96. * 与Array相关的其他方法.
  97. *
  98. * */
  99. @Test
  100. def otherArrayFunction(){
  101. val array = Array(1,3,2,5,5)
  102. // 求和运算
  103. array.sum
  104. // 排序
  105. array.sorted
  106. // 倒叙
  107. array.sorted.reverse
  108. array.sortBy(x=>x)
  109. // 降叙
  110. array.sortWith(_>_)
  111. // 升序
  112. array.sortWith(_<_)
  113. // 写成方法体
  114. array.sortWith((x,y) => (x>y))
  115. array.sortWith((x,y) => (x<y))
  116. }
元组

数组中的元素都是相同元素. 但是要应对不同元素组成的集合. 这在Scala内提供了新的数据集合:元组.

  1. @Test
  2. def initTuple(){
  3. // Tuple的三个值可以不相同.
  4. val tuple1 = (1,"Spark",2.0)
  5. // 映射和Map是特殊的元组 也就是对偶元组
  6. val pairTuple = ("T",5)
  7. var m = Map(("b",2),("a",10))
  8. m += pairTuple
  9. m += (("A",1),("B",2))
  10. // x y z的方式取值
  11. val tupleXYZ, (x,y,z) = (1,"Spark",2.0)
  12. val array = Array(("a",1),("b",2))
  13. // 转换为对偶元组
  14. array.toMap
  15. // 拉链操作
  16. val arrayZip1 = Array("a","b","c")
  17. val arrayZip2 = Array("1","2","3","4")
  18. // 拉链对应转换. 但是有多的元素则不会再使用.
  19. arrayZip1.zip(arrayZip2)
  20. }
集合

Scala内的常用集合除了数组元组外, 还有ListMapSet.
值得一提的是, Scala内有可变集合import scala.collection.mutable.HashSet与不可变集合import scala.collection.immutable.HashSet.不可变集合多用于多线程中的某些数据的共享.
其基本使用主要如下所示:

  1. /**
  2. * Scala 的集合三大类型: 序列 Seq 集Set 映射Map.
  3. * 所有的集合都扩展自Iterable特质.
  4. * 在Scala中集合有可变(mutable)和不可变(immutable)两种类型.
  5. * immutable类型的集合初始化后即不可改变.(与val关键字不同. 主要用于多线程的常量场景.)
  6. *
  7. *
  8. * */
  9. class QuickCollection {
  10. // Sequence 序列相关操作
  11. @Test
  12. def immutableListOperation(){
  13. val list = List(1,2,3)
  14. // 使用ListBuffer
  15. val listBuffer = ListBuffer(1,2,3)
  16. listBuffer(1) = 200
  17. val newListBuffer = listBuffer.map(_*10)
  18. // 其他操作
  19. val list1 = List(1,2,3)
  20. val list2 = 0::list1
  21. val list3 = list1.::(0)
  22. val list4 = 0+:list1
  23. val list5 = list1.+:(0)
  24. // 将一个元素加入到list后面形成新的集合
  25. val lsit6 = list1 :+3
  26. val list0 = List(4,5,6)
  27. // 两个集合合并成为新的集合
  28. val list7 = list1++list0
  29. val list8 = list1 ++: list0
  30. }
  31. @Test
  32. def mutableListOperation(){
  33. // 构建一个可变列表, 初始有三个元素1,2,3
  34. val list0 = ListBuffer[Int](1,2,3)
  35. // 创建一个空的可变列表
  36. val list1 = new ListBuffer[Int]
  37. // 向list1中追加元素, 注意没有生成新的集合
  38. list1 += 4
  39. list1.append(5)
  40. list1.append(1,2,3,4,5)
  41. list1 ++= list0
  42. val list2 = list1 ++ list0
  43. list0 ++= list1
  44. }
  45. // HashSet 也有Immutable与Muttable 可变与不可变的两个版本.
  46. @Test
  47. def immuttableSetOperation(){
  48. val set1 = new HashSet[Int]()
  49. // 将元素与set1合并成为一个新的set
  50. val set2 = set1 +1
  51. // set中的元素不能重复
  52. val set3 = set1 ++ Set(5,6,7)
  53. val set0 = Set(1,2,3) ++ set1
  54. println(set0.getClass)
  55. }
  56. // 可变的set的相关操作
  57. @Test
  58. def muttableSetOperation(){
  59. // 创建一个可变的HashSet
  60. val set1 = new scala.collection.mutable.HashSet[Int]()
  61. // 向HashSet内添加元素
  62. set1 += 2
  63. // add等价于+=
  64. set1.add(4)
  65. set1 ++= Set(1,3,5)
  66. // 删除一个元素
  67. set1 -= 5
  68. set1.remove(2)
  69. println(set1)
  70. }
  71. // 不可变Map
  72. @Test
  73. def immutableMapOperation(){
  74. val map1 = new HashMap[String, Int]()
  75. }
  76. @Test
  77. def mutableMapOperation(){
  78. val map1 = new scala.collection.mutable.HashMap[String, Int]()
  79. // 向Map内添加元素
  80. map1("spark") =1
  81. map1 += (("hadoop",2))
  82. map1.put("storm", 3)
  83. println(map1)
  84. //从map中移除元素
  85. map1 -= "spark"
  86. map1.remove("hadoop")
  87. println(map1)
  88. }
  89. @Test
  90. def initMap(){
  91. // immutable 不可改变
  92. val map1 = Map("a"->1, "b"->2)
  93. // mutable 可以改变
  94. // import scala.collection.mutable.Map
  95. val map2 = Map("A"->1, "B" ->2)
  96. // 访问和修改映射中的值
  97. map2("A")=2
  98. map2("C")=100
  99. map2+=("D"->999)
  100. map2+=(("F",2))
  101. //import java.util.HashMap
  102. // 载入Java的HashMap
  103. val hm = new HashMap()
  104. val map3 = Map(("a",1),("B",2))
  105. map3.getOrElse("C", "123")
  106. }
  107. }

Reference

[1]. Scala 教程
[2]. Scala:HelloWorld
[3]. Scala(二) 基础语法

发表评论

表情:
评论列表 (有 0 条评论,394人围观)

还没有评论,来说两句吧...

相关阅读

    相关 scala基础语法

    1.变量 scala中变量有两种类型:可变型和不可变型。 可变型:变量的值可以在声明后进行修改; 不可变型:变量的值在声明后无法被修改。 scala中使用va

    相关 Scala基础语法

    如果你之前是一名 Java 程序员,并了解 Java 语言的基础知识,那么你能很快学会 Scala 的基础语法。 Scala 与 Java 的最大区别是:Scala 语句末尾