超强总结,用心分享丨大数据超神之路(一):Scala基础语法副本

大数据开发基础

   学习编程语言往往是我们开启学习之路的第一大步。大数据领域的很多框架都是基于Java语言开发的,而且各种框架也都提供了Java API来提供使用和操作接口,所以Java语言的学习逃不掉。除此之外Scala在必要时也可以学一下,在大数据开发领域里用得还是挺多的。Scala语言的表达能力很强,代码信噪比很高,而且很多大数据框架也都提供了Scala语言的开发接口,况且Scala也可以运行于Java平台(JVM),并且兼容Java程序,所以也可以和大数据相关系统进行很好的集成。


前言

  如果你想在下一个项目中使用Scala,这个副本就是为你准备的。除此之外,本副本对于那些想要学习新知识从而开阔自己眼界的程序猿也同样有益。比如说,如果你是Java程序猿,那么阅读本副本,你将接触到来自函数式编程领域和高阶面向对象领域的许多概念,未来很美好,当下很残酷,祝大家都能有一个光明的未来。
  我假定大家拥有常规的编程知识。虽然Scala作为用于入门的编程知识并没有什么不妥,但是Scala并不是一门可以从零基础入门到精通的语言。大部分人都是在Java平台上使用Scala的,因此我会有时将Scala与Java对比,帮助大家理解他们之间的区别。
特点

  • 同样运行在JVM上,可以与现存程序同时运行。
  • 可直接使用Java类库。
  • 同Java一样静态类型。
  • 语法和Java类似,比Java更加简洁(简洁而并不是简单),表达性更强。
  • 同时支持面向对象、函数式编程。
  • 比Java更面向对象。

一、环境配置

  Scala需要依赖Java,访问链接: Scala和jdk对应关系
  Windows中下载安装配置环境变量:

  • 类似于java配置SCALA_HOME为安装目录。
  • 添加%SCALA_HOME%\bin到path环境变量。

  Linux中类似,可以使用包管理器,但如果依赖版本不严格一致的话,需要官网下载对应版本安装即可。
IDEA 环境配置
使用IntelliJ IDEA:

  1. 创建Maven项目,JDK版本8。
  2. 安装插件:Scala。一般默认都已经装了。
  3. Maven项目默认用Java写,在main/目录下新建目录scala/,然后将目录标记为Source Root。
  4. 这样甚至可以在同一个项目中混用Scala和Java源文件,并互相调用。
  5. 需要能够添加scala源文件,右键项目,添加框架支持,配置Scala SDK,选择,然后就可以右键添加Scala源文件了。
  6. 添加包,添加Scala类,选择对象,编辑源码。

package VeryStarted

package VeryStarted

object HelloWorld {
  def main(args: Array[String]): Unit= {
    println("Hello,world!")
  }
}

语法含义:

object SingletonObject { body }
def MethodName(ArgName: ArgType): RetType = { body }

  object关键字创建的伴生对象,可以理解为替代Java的static关键字的方式,将静态方法用单例对象的实例方法做了替代,做到了更纯粹的面向对象。
  再用一个等价的类定义来认识和区别一下Scala和Java:
java

public class Student {
    private String name;
    private Integer age;
    private static String school = "XDU";

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public void printInfo() {
        System.out.println(this.name + " " + this.age + " " + Student.school);
    }

    // psvm
    public static void main(String[] args) {
        Student tch = new Student("tch", 20);
        tch.printInfo();
    }
}

Scala

package VeryStarted

class Student(name: String, age: Int) {
  def printInfo(): Unit = {
    println(name + " " + age + " " + Student.school)
  }
}

// 引入伴生对象,名称一致,同一个文件
object Student {
  val school: String = "XDU"

  def main(args: Array[String]): Unit = {
    val tch = new Student("tch", 20)
    tch.printInfo()
  }
}

二 、变量与数据类型

注释:

  • 和java一样
  • // 单行
  • /* */ 多行
  • /** */ 文档,方法或者类前面,便于scaladoc生成文档。

变量和常量

var name [:VariableType] = value // variable
val name [:ConstantType] = value // constant

  因为Scala的函数式编程要素,所以一个指导意见就是能用常量就不要用变量。这是因为在真正的函数式编程语言里面,var j=20,之后j就不应该变了,所以真正的函数式编程语言里面是没有变量这个概念的。所以常量值的适用,是真正符合函数式编程语言思想的。Scala主要是为了兼容Java面向对象的用法,所以还要把变量这样的使用方法定义出来,但是Scala真正推荐的还是函数式编程思想。

  • 声明变量时,类型可以省略,编译器会自动推导。
  • 静态类型,类型经过给定或推导确定后就不能修改。
  • 变量和常量声明时,必须有初始值。
  • 变量可变,常量不可变。
  • 引用类型常量,不能改变常量指向的对象,可以改变对象var类型的属性字段。
  • 不以;作为语句结尾,scala编译器自动识别语句结尾。

标识符命名规范

  Scala对各种变量、函数、方法等命名时使用字符序列成为标识符,即凡是可以自己起名字的地方都可以称为标识符

  • 字母下划线开头,后跟字母数字下划线,和C/C++/Java一样。
  • 操作符开头,且只包含(±*/#!等),也是有效的标识符。这样用会用什么奇怪的好处吗?答案是灵活到天顶星的运算符重载。
  • 用反引号包括的任意字符串,即使是同39个Scala关键字同名也可以。

关键字

  • package import class obejct trait extends with type for
  • private protected abstract sealed final implicit lazy override try
    catch finlly throw
  • if else match case do while for return yield
  • def var val
  • this super
  • new
  • true false null
  • 其中Java没有的关键字:object trait with implicit match yield def val var

数据类型

  • java中不是纯粹的面向对象。Scala吸取了这一点,所有数据都是对象,都是Any的子类。
  • Any有两个子类:AnyVal值类型 AnyRef引用类型。
  • 数值类型都是AnyVal子类,和Java数值包装类型都一样,只有整数在scala中是Int、字符是Char有点区别。
  • StringOps是java中String类增强,AnyVal子类。
  • Unit对应java中的void,AnyVal子类。用于方法返回值的位置,表示方法无返回值,Unit是一个类型,只有一个单例的对象,转成字符串打印出来为()。
  • Void不是数据类型,只是一个关键字。
  • Null是一个类型,只有一个单例对象null就是空引用,所有引用类型AnyRef的子类,这个类型主要用途是与其他JVM语言互操作,几乎不在Scala代码中使用。
  • Nothing所有类型的子类型,也称为底部类型。它常见的用途是发出终止信号,例如抛出异常、程序退出或无限循环。

空类型

  • Unit 无值,只有一个实例,用于函数返回值。
  • Null 只有一个实例null,空引用。
  • Nothing 确定没有正常的返回值,可以用Nothing来指定返回值类型。

字符串

  • 类型:String
  • +号连接
  • *字符串乘法,复制一个字符串多次拼接
  • printf格式化输出,printf(%d岁的%s在学习,age,name),是对C语言的一种扩展。
  • 字符串模板(插值字符串):s"${varname}"
  • 模板字符串,前缀f格式化模板字符串,通过$获取变量值,%后跟格式化字符串,例如println(f"The num is ${age}2.2f")。
  • 原始字符串:raw"rawstringcontents${var}",不会考虑后跟的格式化字符串。
  • 多行字符串:“”" “”",三引号表示字符串,保持多行字符的原格式输出。
  • 输出:print printf println …

整数类型

  • Byte 1字节
  • Short 2字节
  • Int 4字节
  • Long 8字节
  • 整数赋初值超出表示范围报错。
  • 自动类型推断,整数字面值默认类型Int,长整型字面值必须加L后缀表示
  • 直接向下转换会失败,需要使用强制类型转换,(a + 10).toByte

浮点类型

  • Float IEEE 754 32位浮点数
  • Double IEEE 754 64位浮点数
  • 字面值默认Double

字符类型

  • 同java的Character,2字节,UTF-16编码的字符。
  • 字符常量:‘’
  • 类型Char
  • 转义:\t \n \r \ " 'etc

类型转换

数值类型自动转换

  当 Scala 程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数值类型,这个就是自动类型转换(隐式转换)。数据类型按精度(容量)大小排序为:
在这里插入图片描述

  1. 自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成
    精度大的那种数据类型,然后再进行计算。
  2. 把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动
    类型转换。
  3. (byte,short)和 char 之间不会相互自动转换。
  4. byte,short,char 他们三者可以计算,在计算时首先转换为 int 类型。

强制类型转换

  自动类型转换的逆过程,将精度大的数值类型转换为精度小的数值类型。使用时要加上
强制转函数,但可能造成精度降低或溢出,格外要注意。

Java : int num = (int)2.5
Scala : var num : Int = 2.7.toInt
  • 将数据由高精度转换为低精度,就需要使用到强制转换
  • 强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级

数值类型和String类型之间相互转换

  • 基本类型转 String 类型(语法:将基本类型的值+“” 即可)

  • String 类型转基本数值类型(语法:s1.toInt、s1.toFloat、s1.toDouble、s1.toByte、

三、运算符

算术运算符

在这里插入图片描述
  对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整
数部分而舍弃小数部分。

关系运算符

在这里插入图片描述
  ==更加类似于 Java 中的 equals,参照 jd 工具,==更加类似于 Java 中的 equals,参照 jd 工具。

逻辑运算符

  用于连接多个条件(一般来讲就是关系表达式),最终的结果也是一个 Boolean 值。
假定:变量 A 为 true,B 为 false,运算符描述 。
在这里插入图片描述

赋值运算符

  赋值运算符就是将某个运算后的值,赋给指定的变量。
在这里插入图片描述
  注意:Scala 中没有++、–操作符,可以通过+=、-=来实现同样的效果。

位运算符

  下表中变量 a 为 60,b 为 13。
在这里插入图片描述
运算过程:60<<2=60*(22)=240,**13>>2=13/(22)=4这里不是3,因为是补码操作,向下取整,所以是-4,如果是正13,则是3**

Scala 运算符本质

  在 Scala 中其实是没有运算符的,所有运算符都是方法。这就一切皆对象,这才是真正意义上的面对对象的思路。

-为了兼容JAVA和C中的写法,当调用对象的方法时,点.可以省略

  • 如果函数参数只有一个,或者没有参数,()可以省略
object TestOpt {
 def main(args: Array[String]): Unit = {
 // 标准的加法运算,以自己为加数,然后传入另外一个参数作为加数
 val i:Int = 1.+(1)
 // (1)当调用对象的方法时,.可以省略
 val j:Int = 1 + (1)
 // (2)如果函数参数只有一个,或者没有参数,()可以省略
 val k:Int = 1 + 1
 
 println(1.toString())
 println(1 toString())
 println(1 toString)
 }
}

四、流程控制

  常见的编程语言里流程控制的方式有三种:顺序、分支、和循环。

if-else

单分支

if (条件表达式) { 执行代码块 }

双分支

if (条件表达式) { 执行代码块 1 } else { 执行代码块 2 }

多分支

if (条件表达式 1) { 执行代码块 1 } else if (条件表达式 2) { 执行代码块 2
Scala 中 if else 表达式其实是有返回值的,并且不用写return,具体返回值取决于满足条件的
代码体的最后一行内容。
Scala 中返回值类型不一致,取它们共同的祖先类型。

object TestIfElse {
 def main(args: Array[String]): Unit = {
 println("input age")
 var age = StdIn.readInt()
 val res :String = if (age < 18){
 "童年"
 }else if(age>=18 && age<30){
 "中年"
 }else{
 "老年"
 }
 println(res)
 }
}
def main(args: Array[String]): Unit = {
 println("input age")
 var age = StdIn.readInt()
 val res:Any = if (age < 18){
 "童年"
 }else if(age>=18 && age<30){
 "中年"
 }else{
 100
 }
 println(res)
 }

  Java 中的三元运算符可以用 if else 实现,如果大括号{}内的逻辑代码只有一行,大括号可以省略。如果省略大括号,if 只对最近的一行逻辑代码起作用。

object TestIfElse {
 def main(args: Array[String]): Unit = {
 // Java
// int result = flag?1:0
 // Scala
 println("input age")
 var age = StdIn.readInt()
 val res:Any = if (age < 18) "童年" else "成年"
"不起作用"
 println(res)
 }
}

嵌套分支
  在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层。
分支外面的分支结构称为外层分支。嵌套分支不要超过 3 层。

object TestIfElse {
 def main(args: Array[String]): Unit = {
 println("input age")
 var age = StdIn.readInt()
 val res :String = if (age < 18){
 "童年"
 }else {
 if(age>=18 && age<30){
 "中年"
 }else{
 "老年"
 }
 }
 println(res)
 }
}

Switch 分支结构

  在 Scala 中没有 Switch,而是使用模式匹配来处理。

循环控制

  Scala 也为 for 循环这一常见的控制结构提供了非常多的特性,这些 for 循环的特性被称
为 for 推导式或 for 表达式。
范围数据循环TO

for(i <- 1 to 3){
 print(i + " ")
}
println()

范围数据循环(Until)

for(i <- 1 until 3) {
 print(i + " ")
}
println()

循环守卫

for(i <- 1 to 3 if i != 2) {
 print(i + " ")
}
println(

循环步长
举例:输出 1 到 10 以内的所有奇数

for (i <- 1 to 10 by 2) {
 println("i=" + i)
}

结果

i=1
i=3
i=5
i=7
i=9

嵌套循环
即java中的双层for循环

for(i <- 1 to 3; j <- 1 to 3) {
 println(" i =" + i + " j = " + j)
}

引入变量

for(i <- 1 to 3; j = 4 - i) {
 println("i=" + i + " j=" + j)
}
  • for 推导式一行中有多个表达式时,所以要加 ; 来隔断逻辑
  • for 推导式有一个不成文的约定:当 for 推导式仅包含单一表达式时使用圆括号,
    当包含多个表达式时,一般每行一个表达式,并用花括号代替圆括号,如下
for {
 i <- 1 to 3
j = 4 - i
} {
 println("i=" + i + " j=" + j)
}

倒序打印

for(i <- 1 to 10 reverse){
 println(i)
}

While 循环

  • 与 for 语句不同,while 语句没有返回值,即整个 while 语句的结果是 Unit 类型()

  • 因为 while 中没有返回值,所以当要用该语句来计算并返回结果时,就不可避免
    的使用变量,而变量需要声明在 while 循环的外部,那么就等同于循环的内部对外部的变量
    造成了影响,所以不推荐使用,而是推荐使用 for 循环。

循环中断

  Scala 内置控制结构特地去掉了 break 和 continue,是为了更好的适应函数式编程,推
荐使用函数式的风格解决break和continue的功能,而不是一个关键字。Scala中使用breakable
控制结构来实现 break 和 continue 功能。
采用 Scala 自带的函数,退出循环

import scala.util.control.Breaks
def main(args: Array[String]): Unit = {
 Breaks.breakable(
 for (elem <- 1 to 10) {
 println(elem)
 if (elem == 5) Breaks.break()
 }
 )
 println("正常结束循环")
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值