Scala学习历险记(第一天)
Scala学习笔记(一)
前言:由于最近要整大数据相关的东西,所以java开发的我很苦逼的来学习Scala了,为接下来的工作做知识储备,今天是2021年8月19号,是我接触scala语言的第一天,因此整理一下一天所得,可能比较简单基础,但作为第一次接触而言,算是不少收获了,之后也会在学习的过程中边整理边总结。下面这段话是百度上看到的Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。Scala 运行在 Java 虚拟机上,并兼容现有的 Java 程序。Scala 源代码被编译成 Java 字节码,所以它可以运行于 JVM 之上,并可以调用现有的 Java 类库。
可见scala语言和java的密不可分,接下来的学习也会结合它俩的特性来进行总结。
安装及配置Scala的环境
- 首先自己电脑上先拥有Java 8或者11的运行环境,具体可以参考https://www.runoob.com/java/java-environment-setup.html这一块不再赘述。
- 下载scala的安装包,在http://www.scala-lang.org/downloads上,这里我选择的是scala2版本,比较稳定,我下载的是scala-2.13.6.msi。
- 下载下来之后直接双击安装scala,注意选择安装目录时文件夹不要有空格,我第一次安装在了Program Files (x86),结果一直提示我
'scala' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
,更换目录后就好了。 - 配置环境变量,这里的配置和java及其相似,只不过要新建一个变量名为SCALA_HOME,变量值为scala安装路径的系统环境变量(java建的是JAVA_HOME)。然后在Path内添加上"%SCALA_HOME%\bin"即可
- 因为我是用的idea开发,因为首先我先去了IDEA中的file->setting->Plugins中搜索了Scala插件,下载下来安装后重启idea
- 然后新建项目和java的步骤如出一辙,只不过选择类型时不要选择java,要选择Scala,一路next,最后刚建出来时要等一会儿,因为它这里需要下载相关的依赖jar一类的,我大约等了十几分钟吧。等到加载完,就可以新建scala文件,进行愉快的开发了。
Scala的基本操作用法
scala和java很大的区别在于它每一行语句结束后,可以不用写;
,但是在一行里想编写多个不同的语句,就需要用;
分隔开,scala和java很多的关键字都是一样的,只不过是使用的语法上有所差异,接下来便通过我写的一些demo来感受scala的用法吧,就不再啰里啰嗦的讲学术了。我也是初学者,有不对的多多指教。
scala的常规使用
/**
* scala基础
* @author: zae
* @date: 2021/8/19
* @time: 11:09
*/
object FirstScala {
/**
*
* @param args
*/
def main(args: Array[String]) {
// 第一个scala方法=输出 Hello World
println("Hello, world!")
// 定义变量: var关键字
var name : String = "Zae";println("我的名字叫:"+name);name = "aaa"
var age : Int = 25; println("我的年龄是"+age);
// 定义常量: val关键字,不能修改
val address : String = "北京";
// 支持多个变量声明
var num1,num2 = 100
// 元祖
var po:(Int,String) = (40,"four"); println(po)
// for循环的使用
println("=========for循环的使用=============")
var i = 0;
for (i <- 10 to 20){
// 这里值的是从10循环到20
println("for in to:"+i)
}
for(i <- 10 until 20){
// 这里指的是从10循环到19,就是不包含最后的那个20了
println("for in until"+i)
}
var j = 0;
for(i <- 1 to 4;j <- 1 to 3){
// 罗列出了所有i和j组合的可能性,类似于java中的双重for循环
println("i="+i+"||j="+j);
}
// for循环结合集合使用
val newList = List(2,3,4,5,6,7,8)
for(i <- newList){
println("集合for使用:"+i)
}
// for+if过滤
for(i <- newList
if i>=3;if i<=7){
// 意思是遍历newList,并筛选出大于等于3和小于等于7的元素
println("过滤后的结果为:"+i)
}
// for使用yield,将过滤结果进行存储
val result = for{i<-newList
if i>=4;if i<=6}yield i
// 输出返回值
for(i <- result){
println("收集的结果为"+i)
}
println("============while和do while的使用")
var a = 0
while (a<=5){
a = a+1
println("while的第"+a+"次循环")
}
do{
println(" do while的第"+a+"次循环")
a=a+1
}while(a<=10)
}
scala关于访问修饰符
/**
* 关于访问修饰符
* @author: zae
* @date: 2021/8/19
* @time: 11:41
*/
class TwoScala {
// private访问修饰符,成员对象定义的类以及其内部类可见
class InnerOne{
private def f(){println("f")}
class InnerMost{
f()
}
}
// protected访问修饰符 只允许子类访问
protected def testM(){println("protected")}
class TwoScalaSmall extends TwoScala{
testM()
}
// public都可以访问,默认情况就是public
class InnerTwo{
def testPub(){println("public")}
}
class InnerThree{
(new InnerTwo).testPub()
}
}
Scala函数和方法
Scala函数这一块看起来要比java精彩一些,种类特别多,除了基础常见的定义函数加调用,还有10种比较特殊的,分别是函数传名调用(Call-by-Name),函数 - 可变参数,默认参数值,内嵌函数,偏应用函数,指定函数参数名,递归函数,高阶函数,匿名函数,函数柯里化(Function Currying)。下面将通过我的demo演示各种函数的用法,有些解释直接写在注释中了。
import java.util.Date
/**
* scala函数和方法
* @author: zae
* @date: 2021/8/19
* @time: 14:44
*/
object SecondScala {
def main(args: Array[String]){
// 调用sum方法
println("1+2="+sum(1,2))
// 调用无参无返回方法
outWord()
// 传名调用使用
dealTime(getNowTime())
// 调用可变参数函数
useParams("无尽","名刀","末世")
// 调用含默认参数的方法-不传参
println("不传参:a+b="+defaultParam())
// 调用含默认参数的方法-传参
println("传参:a+b="+defaultParam(100,200))
// 调用内嵌函数
println("内嵌函数结果为:"+innerFun(4))
// 调用偏应用函数
appFunc();
// 指定参数名进行调用
nameFun(b = 10,a = 20)
// 调用递归函数
println("5的阶乘结果为:"+factFun(5))
// 高阶函数
println(apply(layout,10))
// 调用匿名函数
println("调用匿名函数的结果为:"+multFun(2,3))
// 调用柯里化后的函数
println("函数柯里化:"+addFunKe(5)(6))
// 调用闭包类的函数
println("闭包:"+multOneFun(10))
}
// 定义一个方法计算a+b
def sum(a:Int,b:Int) : Int = {
var num : Int = 0
num = a+b
return num
}
// 定义一个无返回值的方法
def outWord(): Unit={
println("我是一个无参无返回值的方法")
}
def getNowTime() = {
println("获取时间,单位为纳秒")
System.nanoTime()
}
// 定义传名方法
def dealTime(t: =>Long) = {
println("在dealTime方法内部")
println("当前时间:"+t)
t
}
// 定义可变参数函数
def useParams(args:String*) ={
var i : Int = 0
for(arg <- args){
println("args["+i+"]="+arg)
i = i+1
}
}
// 定义含默认参数的函数
def defaultParam(a:Int = 10,b:Int = 20):Int = {
var num : Int = 0
num = a+b
num
}
// 内嵌函数
def innerFun(a:Int):Int={
def fact(i:Int,defaultNum:Int):Int = {
if(i<=1)
defaultNum
else
fact(i-1,i*defaultNum)
}
fact(a,1)
}
// 偏应用函数
def appFunc() = {
println("===开启偏应用函数的调用模式===")
val date = new Date
val logWithDate = log(date,_:String)
logWithDate("message1")
logWithDate("message2")
logWithDate("message3")
}
def log(date:Date,message:String) = {
println(date+"===="+message)
}
// 指定函数参数名
def nameFun(a:Int,b:Int): Unit ={
println("===开始指定参数名进行调用===")
println("a的值:"+a)
println("b的值:"+b)
}
// 递归函数,求a的阶乘
def factFun(a:BigInt) : BigInt = {
if (a==1)
1
else
a*factFun(a-1)
}
// 高阶函数
def apply(f:Int => String,v:Int) = f(v)
def layout[A](x:A) = "["+x.toString+"]"
// 匿名函数
val multFun = (i:Int,j:Int) => i*j
// 函数柯里化
def addFunKe(a:Int)(b:Int) = a+b
// 闭包:返回值依赖于声明在函数外部的一个或者多个变量
var numOne = 10;
val multOneFun = (a:Int)=>a*numOne
}
Scala常用数据结构一
这一部分不是包含所有的数据结构,只涉及到字符串,数组以及List集合的相关知识。后续的补充会在学习后进行总结。
import Array._
/**
* Scala常用的数据结构一:字符串,数组,List集合
* @author: zae
* @date: 2021/8/19
* @time: 16:21
*/
object ThreeScala {
def main(args: Array[String]): Unit = {
// 调用关于字符串的方法
strBuf()
// 调用数组方法
arrFun()
// 调用List列表方法
listFun()
}
// 关于字符串的相关知识
def strBuf() = {
val buf = new StringBuilder;
buf += 'a'
buf ++= "bcdef"
println("buf is : "+buf.toString())
var str1 = "yyyyyy.com"
println("yyyyyy.com的长度为"+str1.length())
var str2 = "琴键的空间"
println("str1和str2的连接结果为"+str1.concat(str2))
var floatVar = 12.456
var intVar = 10
var stringVar = "ZAE"
var fs = printf("浮点型变量为%f,整型变量为%d,字符串为%s",floatVar,intVar,stringVar)
println(fs)
}
// 关于数组
def arrFun() = {
// 第一种声明数组的方式
var z1 = new Array[String](3)
z1(0) = "java";z1(1) = "python";z1(2) = "scala"
// 第二种声明数组的方式
var z2 = Array("java","python","scala")
// 数组处理
var myList = Array(1.9,3.8,5,6.1)
var total = 0.0
for(i <- 0 to myList.length-1){
total += myList(i)
}
println("数组的总和为:"+total)
var maxNum = myList(0)
for(i <- 0 to myList.length-1){
if(myList(i)>maxNum)
maxNum = myList(i)
}
println("最大值为:"+maxNum)
// 多维数组
val arrMany = Array.ofDim[Int](3,3)
for(i<-0 to 2;j<-0 to 2){
arrMany(i)(j) = i+j
}
// 打印二维阵列
for(i<-0 to 2;j<-0 to 2){
println("打印二维数组的结果为:arrMany["+i+"]["+j+"] = "+arrMany(i)(j))
}
// 合并数组
var myList1 = Array(1,2,3,4)
var myList2 = Array(5,6,7,8)
var myList3 = concat(myList1,myList2)
for(x <- myList3){
print(x+"|")
}
// 区间数组
var rangeList1 = range(10,20,2)// 从10-20,每隔2个算一个元素
var rangeList2 = range(10,20)// 10-20之间所有的整数都是集合元素
for(x <- rangeList1){
print(" "+x)
}
for (elem <- rangeList2) {
print(" "+elem)
}
}
// 关于scala - List集合
def listFun() = {
// 字符串列表(以下为2种写法,后面同理)
val site:List[String] = List("Java","python","Scala")
var siteN = "Java"::("python"::("Scala"::Nil))
//空列表
val empty:List[Nothing] = List()
val emptyN = Nil
//二维列表
var dim:List[List[Int]] =
List(
List(1,0,0),
List(0,1,0),
List(0,0,1)
)
var dimR = (1::(0::(0::Nil))) ::
(0::(1::(0::Nil))) ::
(0::(0::(1::Nil))) :: Nil
println("第一个语言是"+site.head)
println("最后一个语言是"+site.tail)
println("列表site是否为空:"+site.isEmpty)
println("列表empty是否为空"+empty.isEmpty)
// 连接列表的三种方式
val word1:List[String] = List("Java","python","Scala")
val word2:List[String] = List("C","C++","Html")
// way1:使用:::运算符
var wordResult = word1:::word2
// way2:使用List.:::()方法
wordResult = word1.:::(word2)
// way3:使用concat方法
wordResult = List.concat(word1,word2)
println("word1和word2连接后的结果是:"+wordResult)
//List.fill()创建一个指定重复数量的元素列表
val fillList = List.fill(3)("scala")
println("重复scala三次:"+fillList)
//List.tabulate() 方法是通过给定的函数来创建列表
val taListOne = List.tabulate(6)(n=>n*n)
println("一维:"+taListOne)
val talListTwo = List.tabulate(3,4)(_*_)
println("多维:"+talListTwo)
}
}
第一天就搭建了下环境和学习了下比较基础简单的用法,以后可能会愈来愈难,但是一定要坚持下去!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端