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

版权声明:欢迎转载,转载请说明出处. 大数据Github项目地址https://github.com/SeanYanxml/bigdata。 https://blog.csdn.net/u010416101/article/details/89638288

前言

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

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


前置准备

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

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

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.yanxml</groupId>
	<artifactId>quick-scala</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>${project.artifactId}</name>
	<description>My wonderfull scala app</description>
	<inceptionYear>2010</inceptionYear>
	<licenses>
		<license>
			<name>My License</name>
			<url>http://....</url>
			<distribution>repo</distribution>
		</license>
	</licenses>

	<properties>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<encoding>UTF-8</encoding>
		<scala.tools.version>2.11</scala.tools.version>
		<scala.version>2.11.8</scala.version>
	</properties>

	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.7</version>
		</dependency>
		<dependency>
			<groupId>org.scala-lang</groupId>
			<artifactId>scala-library</artifactId>
			<version>${scala.version}</version>
		</dependency>



		<dependency>
			<groupId>org.scala-lang</groupId>
			<artifactId>scala-library</artifactId>
			<version>2.11.8</version>
		</dependency>
		<dependency>
			<groupId>org.scala-lang</groupId>
			<artifactId>scala-compiler</artifactId>
			<version>2.11.8</version>
		</dependency>
		<dependency>
			<groupId>org.scala-lang</groupId>
			<artifactId>scala-reflect</artifactId>
			<version>2.11.8</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.scala-lang/scala-actors -->
		<dependency>
			<groupId>org.scala-lang</groupId>
			<artifactId>scala-actors</artifactId>
			<version>2.11.8</version>
		</dependency>
		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
		<!-- <dependency> <groupId>org.specs2</groupId> <artifactId>specs2_${scala.tools.version}</artifactId> 
			<version>3.0</version> <scope>test</scope> </dependency> -->
		<!-- https://mvnrepository.com/artifact/org.scalatest/scalatest -->
		<dependency>
			<groupId>org.scalatest</groupId>
			<artifactId>scalatest_2.11</artifactId>
			<version>3.0.0-M16-SNAP6</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.scalatest</groupId>
			<artifactId>scalatest_${scala.tools.version}</artifactId>
			<version>3.0.0-M16-SNAP6</version>
			<scope>test</scope>
		</dependency>

		<!-- spark -->
		<dependency>
			<groupId>org.apache.spark</groupId>
			<artifactId>spark-core_2.11</artifactId>
			<version>2.2.1</version>
		</dependency>

		<!-- akka -->
		<!-- https://mvnrepository.com/artifact/com.typesafe.akka/akka-actor -->
		<dependency>
			<groupId>com.typesafe.akka</groupId>
			<artifactId>akka-actor_2.11</artifactId>
			<version>2.3.14</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.typesafe.akka/akka-remote -->
		<dependency>
			<groupId>com.typesafe.akka</groupId>
			<artifactId>akka-remote_2.11</artifactId>
			<version>2.3.14</version>
		</dependency>

	</dependencies>

	<build>
		<sourceDirectory>src/main/scala</sourceDirectory>
		<testSourceDirectory>src/test/scala</testSourceDirectory>
		<plugins>
			<plugin>
				<!-- see http://davidb.github.com/scala-maven-plugin -->
				<groupId>net.alchim31.maven</groupId>
				<artifactId>scala-maven-plugin</artifactId>
				<version>3.1.3</version>
				<executions>
					<execution>
						<goals>
							<goal>compile</goal>
							<goal>testCompile</goal>
						</goals>
						<configuration>
							<args>
								<arg>-make:transitive</arg>
								<arg>-dependencyfile</arg>
								<arg>${project.build.directory}/.scala_dependencies</arg>
							</args>
						</configuration>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.13</version>
				<configuration>
					<useFile>false</useFile>
					<disableXmlReport>true</disableXmlReport>
					<!-- If you have classpath issue like NoDefClassError,... -->
					<!-- useManifestOnlyJar>false</useManifestOnlyJar -->
					<includes>
						<include>**/*Test.*</include>
						<include>**/*Suite.*</include>
					</includes>
				</configuration>
			</plugin>
		</plugins>
	</build>
</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环境的问题, 绕了好久. 希望各位引以为戒.)

object App {
    
  def main(args : Array[String]) {
    println( "Hello World!" )
  }
}
object HelloWorld extends App{
  println("HelloWorld")
}
常量&变量

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

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

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

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

# Java
int a=0;
if(a>0){
	a++;
}else{
	a--;
}
# Scala
 def ifelse(){
    println("if---else---test")
    val x =  1
    // 判断x的值 返回值给y
    val y = if(x>0) 1 else -1
    println(y)

    // 支持混合类型表达式
    val z = if(x>2) 1 else "error"
    println(z)
    
    // 缺失else 相当于if(x>2) else()
    val m = if(x>2) 1
    println(m)
    
    // scala中有个Unit类, 相当于Java中的void.
    val n = if(x>2) 1 else()
    println(n)
    
    val k = if(x<0) 0 else if(x>2) 1 else -1
    println(k)
  }
代码块(Block)

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

# Java
public static void main(String[]args){
	int a=0;
	int b=0;
}
# Scala
 @Test
  // 块表达式(如何确定block的返回值?)
  def block(){
     println("block---test")
     val x = 0
     val result = {
       if (x>0) -1 else 1
     }
     println(result)
  }
循环(For&While)

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

# java
public static void main(String []args){
	int a=2;
	while(a>0){
		a++;
	}

	do{
		a++;
	}while(a>0)

	for(int i=a;i>0;i++){
		a++;
	}
}
# Scala
@Test
  // 常见的for循环
  def forcycle(){
    println("for---cycle---test")

    // 遍历 to 是一个方法 
    1 to 10
    for(i <- 1 to 10){print(i)}
    println()
    
    // 数组的定义 (相当于使用数组的Object方法 也就是静态方法)
    val arr = Array("a","b","c")
    for(a<-arr){print(a)}
    println()
    
    // 循环带条件, 主要if判断前没有分号
    for(i<- 1 to 3; j<- 1 to 3 if i !=j){
      print(10*(i)+j+" ")
    }
    println()
     
    //for推导式: for的循环的循环体以yield开始, 该循环会构建出一个集合
    // 每次迭代生成集合的一个值
    val v = for(i<-1 to 10) yield i *10
    println(v)
    
    1.to(10).map(_*10)
    
    // 遍历数组
    val arr2 = Array(1,2,3)
    val t = for(i<-arr2) yield i*2
    println(t)
    
    
    // 偶数 奇数获取
    val arrTmp = Array(1,2,3,4,5,6,7,8)
    val arrResult = for(i<-arrTmp){if(i%2==0) i else()}
    val arrResult2  = for(i<-arrTmp ; if(i%2==0)) yield i
    val arrResult3  = for(i<-arrTmp ; if(i%2==0)) i
    val arrResult4 = arrTmp.filter(_%2==0)
    
    for(i <- 1 to arrTmp.length) print(arrTmp(i))
    
    for(i <- 0 until arrTmp.length) println(arrTmp(i))
    
  }
 

Scala do…while 循环

数组&元组

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

#Java
public static void main(String []args){
	String []array1= {"1","2","3"};
	String []array2 = new String[10];
	// 循环遍历1
	for(String str:array2){
	}
	// 循环遍历2
	for(int i=0;i<array2.length;i++){
	}
}
# Scala
  
  @Test
  def initArray(){
    // Test1
     // 初始化一个长度为8的定长数组, 所有元素均为0
    val array1 = new Array[Int](10)
    // 直接打印定长数组, 内容为数组的hashcode值
    println(array1)
    // 将数组转换为缓冲, 可以看到数组内的内容
    // to buffer 将数组转换为缓冲
    println(array1.toBuffer)
    
    // Test2
    // 使用静态方法创建
    val array2 = Array[Int](10)
    println(array2.toBuffer)
    
    // Test3
    val array3 = Array("Hadoop","Strom","Spark")
    println(array3(1))
    
    // 变长数组
    // 如果想使用数组缓冲,需要导入 import scala.collection.mutable.ArrayBuffer包
    val arrayBuffer1 = ArrayBuffer[Int]()
    // 尾部追加一个元素 +=尾部追加元素
    arrayBuffer1 += 1
    // 尾部追加多个元素
    arrayBuffer1 += (2,3,4,5)
    // 追加一个数组 ++=
    arrayBuffer1 ++= Array(6,7)
    // 追加一个缓冲数组 ++=
    arrayBuffer1 ++= ArrayBuffer(8,9) 
    // 打印缓冲
    println(arrayBuffer1)
    
    // 指定位置添加元素
    val arrayBuffer2 = ArrayBuffer[Int]()
    arrayBuffer2 += (1,2,3)
    // 在数组角标为0的位置 开始插入2个元素
    arrayBuffer2.insert(0, -1,0)
    // 在数组角标位置为8的位置删除2个雅俗
    arrayBuffer2.remove(1,2)
    
  }
  
  /**
   * 遍历数组的方式主要有2种
   * 1. for循环
   * 2. 使用until生成角标, 0 until 10 (包含0不包含10 前封后开)
   * 3. map方法
   * */
  @Test
  def foreachArray(){
    // 初始化
    val array = Array(1,2,3,4,5,6)
    
    // 使用for循环
    for(i <- array){
      print(i)
    }
    
    // 使用角标 (有时候需要获取数组的下标)
    // .reverse可以将其进行反转
    for(i<-(0 until array.length)){
      print(array(i))
    }
    
    // 倒转遍历数组
    for(i<-(0 until array.length).reverse){      
    }
    
    // map方式
    // 方法转换为一个函数
    array.map(println(_))

  }
  
  /**
   * 转换数组, 生成一个新的数组
   * 1. yield方式
   * 2. map方法.
   * */
  @Test
  def swapArray(){
    val array = Array(1,2,3,4,5)
    
    // 偶数取出来 乘以10
    val arrayOdd = for(i<- array;if i%2==0)yield i*10
    println(arrayOdd.toBuffer)
    
    
    // map 方式的隐式函数 (一步一步的简化方式)
    array.map((x:Int)=>x*10)
    array.map(x=>x*10)
    array.map(_*10)
    
    val arrayOddMap = array.filter(_%2==0).map(_*10)
    println(arrayOddMap.toBuffer)
    
  }
  
  /**
   * 与Array相关的其他方法.
   * 
   * */
  @Test
  def otherArrayFunction(){
     val array = Array(1,3,2,5,5)

     // 求和运算
     array.sum
     
     // 排序
     array.sorted
     
     // 倒叙
     array.sorted.reverse
     
     array.sortBy(x=>x)
     
     // 降叙
     array.sortWith(_>_)
     
     // 升序
     array.sortWith(_<_)
     
     // 写成方法体
     array.sortWith((x,y) => (x>y))
     array.sortWith((x,y) => (x<y))
  }
元组

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

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

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


/**
 * Scala 的集合三大类型: 序列 Seq 集Set 映射Map.
 * 所有的集合都扩展自Iterable特质.
 * 在Scala中集合有可变(mutable)和不可变(immutable)两种类型.
 * immutable类型的集合初始化后即不可改变.(与val关键字不同. 主要用于多线程的常量场景.)
 * 
 * 
 * */
class QuickCollection {
  
    // Sequence 序列相关操作 
    @Test
    def immutableListOperation(){
      val list = List(1,2,3)
      
      // 使用ListBuffer
      val listBuffer = ListBuffer(1,2,3)
      listBuffer(1) = 200
      val newListBuffer = listBuffer.map(_*10)
      
      
      // 其他操作
      val list1 = List(1,2,3)
      val list2 = 0::list1
      val list3 = list1.::(0)
      val list4 = 0+:list1
      val list5 = list1.+:(0)
      
      // 将一个元素加入到list后面形成新的集合
      val lsit6 = list1 :+3
      
      val list0 = List(4,5,6)
      // 两个集合合并成为新的集合
      val list7 = list1++list0
      val list8 = list1 ++: list0
      
    }
    
    @Test
    def mutableListOperation(){
      // 构建一个可变列表, 初始有三个元素1,2,3
      val list0 = ListBuffer[Int](1,2,3)
      
      // 创建一个空的可变列表
      val list1 = new ListBuffer[Int]
      // 向list1中追加元素, 注意没有生成新的集合
      list1 += 4
      list1.append(5)
      list1.append(1,2,3,4,5)
      
      list1 ++= list0
      
      val list2 = list1 ++ list0
      
      
      
      list0 ++= list1
    }
    
    // HashSet 也有Immutable与Muttable 可变与不可变的两个版本.
    @Test
    def immuttableSetOperation(){
      val set1 = new HashSet[Int]()
      // 将元素与set1合并成为一个新的set
      val set2 = set1 +1
      // set中的元素不能重复
      
      val set3 = set1 ++ Set(5,6,7)
      val set0 = Set(1,2,3) ++ set1
      println(set0.getClass)
      
    }
    
    // 可变的set的相关操作
    @Test
    def muttableSetOperation(){
      // 创建一个可变的HashSet
      val set1 = new scala.collection.mutable.HashSet[Int]()
      // 向HashSet内添加元素
      set1 += 2
      // add等价于+=
      set1.add(4)
      
      set1 ++= Set(1,3,5)
      
      // 删除一个元素
      set1  -= 5
      set1.remove(2)
      println(set1)
    }
    
    // 不可变Map
    @Test
    def immutableMapOperation(){
      val map1 = new HashMap[String, Int]()
      
    }
    
    @Test
    def mutableMapOperation(){
       val map1 = new scala.collection.mutable.HashMap[String, Int]()
       // 向Map内添加元素
       map1("spark") =1
       map1 += (("hadoop",2))
       map1.put("storm", 3)
       println(map1)
       
       //从map中移除元素
       map1 -= "spark"
       map1.remove("hadoop")
       println(map1)

    }
	  @Test
  def initMap(){
    // immutable 不可改变
    val map1 = Map("a"->1, "b"->2)
    
    // mutable 可以改变
    // import scala.collection.mutable.Map
    val map2 = Map("A"->1, "B" ->2)
    // 访问和修改映射中的值
    map2("A")=2
    map2("C")=100
    
    map2+=("D"->999)
    map2+=(("F",2))
    
    //import java.util.HashMap
    // 载入Java的HashMap
    val hm = new HashMap()
    
    val map3 = Map(("a",1),("B",2))
    
    map3.getOrElse("C", "123")
  }
}


Reference

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

展开阅读全文

没有更多推荐了,返回首页