【Scala教程】如何在已掌握的Java知识基础上快速上手Scala?【个人学习记录】

前言

本人同样为学生,总结不一定对,这只是个人在学习过程中的记录,仅供参考。如果内容有问题的话,欢迎在评论区指出,谢谢正在阅读的您~

已经熟悉一门编程语言后,如何快速上手一门新语言?个人观点是注重二者的不同点,比如输入输出的语句格式、声明变量的方式、函数定义的方式等等,具体有哪些规则我没有总结过。
所以这篇内容主要关注的是Java和Scala之间的区别

正文开始!

1. 编译运行

scala xxx.scala

scalac xxx.scala // 编译
scala -classpath . 类名//执行,这里的类名指的是xxx.scala文件中object后面对应的名字

2. 声明变量

var、val

3. 输出

print()
printf(“%s %d %.3f”, “123”, 1, 2.3)
println()

4. 显式指定变量类型

val aa : String = “213”

5. 范围区间

1 to 5 前闭后闭
1 until 5 前闭后开
1 to 5 by 2 前闭后闭、步长为2,超过5的不显示

6. 写入文本文件

import java.io.PrintWriter
val filePath = “./input”;
var out = new PrintWriter(filePath)
out.println(“123”)
out.print(“asaa”)
out.close();
必须执行close()方法后才会在文件中看到内容
执行该方法前,文件若原来有内容,则会被清空,执行了就会写入
会自动创建目标文件,或者覆盖已有的同名文件

7. 读取文本文件

import scala.io.Source
var filePath = “./123”
var inputFile = Source.fromFile(filePath);
var lines = inputFile.getLines
for(line <- lines) pirntln(line)
注意getLines是没有括号的

8. if语句可以赋值给变量,类似三元表达式

var x = 6
var a = if(x>1) 1 else -1
a
执行后,a=1

9. for循环

for(variable <- Iterator) println(variable)
其中,variable是不需要提前定义可以直接使用的,Iterator需要是迭代器类型的变量,如1 to 5或者1 until 5等等

也可以增加条件,类似实现Java中for循环的条件
for(variable <- 1 to 5 if variable%2 == 0) println(variable)
这样就可以筛选所有的偶数

也可以在一个for循环使用多个生成器、给每个变量指定条件,即多个变量
for(i <- 1 to 5 if i % 2 == 1 ; j <- 1 to 5 if j %2 == 0) println(i*j)

for循环还可以用来过滤,即从众多数据筛选部分出来
var a = for(m <- 1 to 5 by 2) yield m
println(a)

10. 数组

下标引用用圆括号而不是方括,
var arr = new Array[Int](3)
val arr = Array(12,45,33)
这是两种声明数组的方式
声明长度为3的Int类型的数组
arr(0) = 1
arr(1) = 2
arr(2) = 3
print(arr(0))
Int型数组声明后自动赋值为0
字符串数组,每个数组元素初始化为null

11. 列表

var a = List(1,2,3)
获取头部元素:
print(a.head) 返回1
获取尾部元素列表:
print(a.tail) 返回List(2, 3)

元素和列表的拼接 ::
print(2 :: 4 :: a) 输出List(2, 4, 1, 2, 3)

列表和列表的拼接 :::
print(List(1,2,3) ::: List(3,4,5) ::: Nil) 输出List(1,2,3,3,4,5), Nil表示空列表

列表求和
a.sum

12. 元组

var a = (1, 2, 3.23, ”123”)
println(a._1, a._2, a._3, a._4) 使用._1、._2可以访问各个元素

13. 集合

声明一个集合:(默认声明的是不可变集合)
var a = Set(1, 2, 3, 4, 5, 1, 2)
println(a)
向集合中增加元素:(一个集合中的元素类型需要相同)
a += 666 (不可变集合的变量必须被声明为var型才能±)
是否包含某元素:
println(a.contains(2))

声明可变集合:
import scala.collection.mutable.Set
可变集合的变量可以是val也可以是var,此时都可以进行±
val mutableSet = Set(“Database”,“BigData”)
不可变集的±会产生一个新的集、不改变原来的集; 可变集的±改变的是该集本身

14. 映射

创建映射和取值:(默认创建的是不可变映射)
val u= Map(“a” -> “1”, “b” -> “2”,“c”->“3”)
println(university(“NEU”))
检查映射是否包含与参数相同的键名:
u.contains(“a”) 返回true

创建可变的映射
import scala.collection.mutable.Map
val u= Map(“a” -> “1”, “b” -> “2”, “c”->“3”)
更新元素
u(“a”) = “111” //更新已有元素的值
添加元素
u(“aaa”) = “aaa” //添加新元素
u += (“z”->”666”, “y”->”555”, “x”->”444”)
循环遍历映射
var u = Map(“a"->”1”, “b”->”2”)
for ((key,value) <- u ) println(key);println(value);
for(key <- u.keys) println(key);
for(value <- u.values) println(value);
u foreach {case(k,v) => println(k+":"+v)}
u.foreach({case(k,v) => println(k+":"+v)})

15. 迭代器

val iter = Iterator(“1”,“2”,“3”)
hasNext一定是没有括号,但是next是可以有括号也可以没有括号
while (iter.hasNext) {
println(iter.next())
}
for (elem <- iter) {
println(elem)
}

16. 类

如何创建类:
class Counter {
private var value = 0
def increment(): Unit = { value += 1}
def current(): Int = {value}
}
class Counter {
private var value = 0
def increment(): Unit = value += 1 //去掉了大括号
def current(): Int = {value} //作为对比,这里依然保留大括号
}

类的综合运用模板:
class Counter {
private var privateValue = 0 //变成私有字段,并且修改字段名称
def value = privateValue //定义一个方法,方法的名称就是原来我们想要的字段的名称
def value_=(newValue: Int){
if (newValue > 0) privateValue = newValue //只有提供的新值是正数,才允许修改
}
def increment(step: Int): Unit = { value += step}
def current(): Int = {value}
}
object MyCounter{
def main(args:Array[String]){
val myCounter = new Counter
println(myCounter.value) //打印value的初始值
myCounter.value = 3 //为value设置新的值
println(myCounter.value) //打印value的新值
myCounter.increment(1) //这里设置步长为1,每次增加1
println(myCounter.current)
}
}
得到三行执行结果,第一行是0,第二行是3,第三行是4

字段前面什么修饰符都没有就默认是public,类不需要声明为public,Scala文件中包含的多个类之间,都是彼此可见的。
Unit是返回值类型,相当于void,没有返回值
方法的返回值,不需要靠return语句,方法最后一个表达式的值就是返回值
Scala在调用无参方法时,是可以省略方法名后面的圆括号的

scalac命令编译时,必须要求把声明(比如val myCounter = new Counter以及myCounter.increment()等)都封装在对象中,这也是JVM字节码的要求。但也可以通过命令在编译时自动将整个xxxx.scala文件打包到指定的类ClassName中

scalac -Xscript ClassName xxxx.scala //编译
scala -classpath . ClassName //执行

17. 构造器

辅助构造器
class Counter {
private var value = 0 //value用来存储计数器的起始值
private var name = “” //表示计数器的名称
private var mode = 1 //表示计数器类型(1表示步数计数器,2表示时间计数器)
def this(name: String){ //第一个辅助构造器
this() //调用主构造器
this.name = name
}
def this (name: String, mode: Int){ //第二个辅助构造器
this(name) //调用前一个辅助构造器
this.mode = mode
}
def increment(step: Int): Unit = { value += step}
def current(): Int = {value}
def info(): Unit = {printf(“Name:%s and mode is %d\n”,name,mode)}
}
主构造器
不用在类中专门定义构造方法,在两个地方进行处理,编写类的代码的时候添加圆括号并直接在圆括号内指定必须要有的参数、调用类的构造器的时候在方法的圆括号内指定要传的所有参数。
class Counter(val name: String, val mode: Int) {
private var value = 0 //value用来存储计数器的起始值
def increment(step: Int): Unit = { value += step}
def current(): Int = {value}
def info(): Unit = {printf(“Name:%s and mode is %d\n”,name,mode)}
}
object MyCounter{
def main(args:Array[String]){
val myCounter = new Counter(“Timer”,2)
myCounter.info //显示计数器信息
myCounter.increment(1) //设置步长
printf(“Current Value is: %d\n”,myCounter.current) //显示计数器当前值
}
}
单例对象
用object关键字,而不是用class关键字。

伴生对象
当单例对象与某个类具有相同的名称时,它被称为这个类的“伴生对象”。类和它的伴生对象必须存在于同一个文件中,而且可以相互访问私有成员(字段和方法)。伴生对象中定义的方法实际上就起到了Java中静态(static)方法的作用

18. 函数式编程

定义一个Scala中的函数:
val counter: Int => Int = { (value) => value += 1 }

匿名函数
myNumFunc后面的类型和参数num的类型定义,必须至少存在一个。
val myNumFunc : Int = (num: Int) => num * 2
println(myNumFunc(3))
结果会输出6

闭包
大概就是函数A内部嵌套一个函数B,但A或者B内部需要用到函数A外部的变量。可以理解为,首先调用函数A,然后函数B就作为函数A的返回值赋值给了调用函数A时赋值的变量a,下一次调用a时实际上调用的是函数B;也可以理解为调用A赋值给a的是函数B的地址,与C语言传递地址的理解方式相似。

高阶函数
函数A的参数或者返回值也为一个函数,则函数A称为高阶函数。
类似于Java实现排序时的多态继承
就是只编码要比较两个参数,但是不硬编码怎么比较两个参数,比较的规则由第三个参数来决定。这第三个参数通常都是一个Comparator。
Python中也有闭包,当初Python课上老师讲过…
总之就是让一个函数A更通用,在A内部,使用函数A参数所对应的函数去决定处理方式。

占位符
val numList = List(-3, -5, 1, 6, 9)
numList.filter(x => x > 0 )
numList.filter(_ > 0)
列表numList中的每个元素都会依次传入用来替换下划线,判断条件是否成立,如果成立,就把该值放入结果集合,如果不成立,则舍弃

遍历操作
遍历列表
var list = List(1,2,3,4)
for (elem <- list) println(elem)
或者:
list.foreach(elem => println(elem)) //本行语句甚至可以简写为list.foreach(println)
或者写成
list foreach println

遍历映射
见映射相关描述

map和flatMap操作
map是针对集合的,map操作可以把一个函数应用到集合的每个元素上,然后将每个元素经过函数过后的结果形成一个集合返回
val books = List(“Hadoop”, “Hive”, “HDFS”)
books.map(s => s.toUpperCase)
输出: List[String] = List(HADOOP, HIVE, HDFS)

flatMap是会对集合的每个元素都返回一个集合,最后再把每个元素返回的集合组合为一个大的集合返回

filter操作
val a = List(1,2,3)
println(a filter {kv => kv >= 2})

reduce和reduceRight操作

val list = List(1,2,3,4,5)
list.reduce(_ - _)
执行过程如下:
( ( ( ( 1 – 2 ) – 3 ) – 4 ) – 5 )

list.reduceRight(_ - _)
执行过程如下:
(1 - ( 2 - ( 3 - ( 4 - 5 ))))

fold操作
其实就是在reduce()的基础上,将reduce换成了fold()
所以fold的基本用法就是
fold(x)()

比如
var a = List(1,2,3)
m+a.reduce(+)
与下面的等价
var a = List(1,2,3)
a.fold(m)(+)

但是在减法的时候,有些不同
var a = List(1,2,3,4)
a.foldLeft(m)(-)
上面代码的执行顺序为:
( ( ( (m – 1) – 2 ) – 3 ) – 4 )

a.foldRight(m)(-)
上面一行代码的执行顺序为:
( 1 – ( 2 – ( 3 – ( 4 – m) ) ) )

鸣谢

本人为在校学生,这篇内容主要是参考学校授课教师的上课内容、参考部分博客(但是没有记录参考了哪些博客…确实也查找了太多的博客没法一一记录,实在抱歉…)、结合自己对Java和Scala的理解写下的。
感谢学校辛苦付出的授课教师!
感谢万能的CSDN上各位聪明的博主!
感谢正在观看并且愿意点个赞的你!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值