Scala入门
-
-
- 一.Scala安装
- 二.类和对象
-
- 1.Scala基本数据类型
- 2.Scala定义类
- 3.Scala单例对象
- 3.重载构造
- 4.类的继承
- 5.伴生对象
- 三.简单语法
-
- 1.if-else
- 2.循环
- 3.方法
- 4.字符串
- 5.数组
- 6.集合
- 四.常用语法
-
- 1.Trait
- 2.Match
- 3.样例类
- 4.隐式值与隐式参数
- 5.隐式转换函数
- 6.隐式类
-
一.Scala安装
https://www.runoob.com/scala/scala-install.html
IDEA创建Scala项目
文章图片
文章图片
二.类和对象
1.Scala基本数据类型 基本与java类似,但首字符要大写
类型 | 说明 |
---|---|
Byte | -128-127 |
Short | -32768-32767 |
Int | -2147483648-2147483647 |
Long | 64位 |
Float | 32位单精度浮点数 |
Double | 64位双精度浮点数 |
Char | 16位无符号Unicode字符 |
Boolean | true或者false |
Unit | 等同void |
Null | null或者空引用 |
Nothing | 类的最底层 |
String | 字符序列 |
Any | 所有类的超类 |
Scala使用关键词 "var" 声明变量,使用关键词 "val" 声明常量,可以省略类型,会自动检测类型
val name = "song";
// 常量
var age = 18// 变量
var num:Int = 10 // 变量
2.Scala定义类
属性定义
:类的括号里可以定义参数,但必须指明类型,格式参数名:类型
,可以看到,类似于java的有参构造函数,有了参数就有了构造,默认有set和get方法,只有var变量可以set方法声明
:def functionName ([参数列表]) : [return type]class Person(xname:String,xage:Int){// 类
val name = xname;
val age = xage;
def sayName(): Unit ={ // 方法
println("My name is - " + Lesson_ClassAndObj.name)
}
}
3.Scala单例对象 在 Scala 中,是没有 static 这个关键字,但是它也为我们提供了单例模式的实现方法,那就是使用关键字object,
object相当于java的单例,定义全是静态的
object Lesson_ClassAndObj {
val name = "static test"// 等同于java中用static声明的属性def main(args: Array[String]): Unit = {// 主函数
val person = new Person("song", 24) // 对象
println(person.name);
// get方法
println(person.age);
// 如果age是var类型person.age = 18相当于调用set方法
person.sayName() // 调用方法
}
}
文章图片
3.重载构造
- 新构造的属性要先在类中声明
- 新构造的第一行必须调用默认的构造
- def this(…){…}
class Person(xname:String,xage:Int){// 类
val name = xname;
val age = xage;
var gender = 'N';
// 也可以var gender : String = __表示占位符def sayName(): Unit ={ // 方法
println("My name is - " + Lesson_ClassAndObj.name);
}def this(xname:String,xage:Int,xgender:Char){// 重载构造
this(xname,xage);
this.gender = xgender;
}
}
bject Lesson_ClassAndObj {
val name = "static test"def main(args: Array[String]): Unit = {// 主函数
val person = new Person("song", 24) // 对象
println(person.name);
// get方法
println(person.age);
person.sayName() // 调用方法val person1 = new Person("kun", 28, 'M');
// 重载构造创建的对象
println(person1.gender);
}
}
文章图片
4.类的继承
override val xc
为重写了父类的字段继承会继承父类的所有属性和方法,
Scala 只允许继承一个父类
var不可以继承
class Person(xname:String,xage:Int){// 类
val name = xname;
val age = xage;
var gender = 'N';
def sayName(): Unit ={ // 方法
println("My name is - " + Lesson_ClassAndObj.name);
}def this(xname:String,xage:Int,xgender:Char){// 重载构造
this(xname,xage);
this.gender = xgender;
}}class Person2(override val name:String, override val age:Int, val xaddress :String) extends Person(name,age){
var address = xaddress;
def sayAll():Unit = {
print("name - "+ name+"- age - "+age+"- address - "+address);
}
}object Lesson_ClassAndObj {
val name = "static test"def main(args: Array[String]): Unit = {// 主函数
val person = new Person("song", 24) // 对象
println(person.name);
// get方法
println(person.age);
person.sayName() // 调用方法val person1 = new Person("kun", 28, 'M');
println(person1.gender);
val person2 = new Person2("zhang", 16, "guangzhou") // 继承的类
person2.sayName() // 调用父类的方法
println(person2.sayAll())
}
}
文章图片
5.伴生对象 当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object。你必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:companion class。类和它的伴生对象可以互相访问其私有成员
默认伴生对象是没有构造参数的,但是我们可以重写apply()方法,当调用有参构造半生对象时,会自动匹配apply()方法
// 私有构造方法
class CompanionTest private(val color:String) {println("创建" + this)override def toString(): String = "颜色标记:"+ color
}// 伴生对象,与类名字相同,可以访问类的私有属性和方法
object CompanionTest{private val markers: Map[String, CompanionTest] = Map(
"red" -> new CompanionTest("red"),
"blue" -> new CompanionTest("blue"),
"green" -> new CompanionTest("green")
)def apply(color:String) = {
if(markers.contains(color)) markers(color) else null
}def getMarker(color:String) = {
if(markers.contains(color)) markers(color) else null
}
def main(args: Array[String]) {
println(CompanionTest("red"))//CompanionTest无参数构造,会匹配apply方法
// 单例函数调用,省略了.(点)符号
println(CompanionTest.getMarker( "blue"))
}
}
文章图片
三.简单语法
1.if-else
object IfElse {
def main(args: Array[String]): Unit = {
var x = 30;
if (x == 10) {
println("X 的值为 10");
} else if (x == 20) {
println("X 的值为 20");
} else if (x == 30) {
println("X 的值为 30");
} else {
println("无法判断 X 的值");
}
}
}
【大数据|Scala语言入门】
文章图片
2.循环
- while 循环 运行一系列语句,如果条件为true,会重复运行,直到条件变为false
- do…while 循环 类似 while 语句区别在于判断循环条件之前,先执行一次循环的代码块
- for 循环 用来重复执行一系列语句直到达成特定条件达成,一般通过在每次循环完成后增加计数器的值来实现
- break 语句 中断循环
object Circle {
def main(args: Array[String]): Unit = {for(num <- 1 to 10){ // 1到10,包括10
print(num+"-");
}
println()for(num <- 1 until(10,2)){// 10到9,步长为2
print(num+"-")
}
println()for(num <- 1 to 10 ;
if(num % 2 == 0) ;
if(num > 5)){ // 可以加判断条件
print(num+"-")
}
println()// 局部变量
var a = 1
// do 循环
do {
print("Value of a: " + a +"-")
a = a + 1
} while ( {
a < 3
})}
}
文章图片
3.方法 def functionName ([参数列表]) : [return type]
- 如果有return,则必须指定返回值类型
- 没有return,默认将最后一行计算的结果当做返回值
- 传入的参数必须指定类型
object Method {
def main(args: Array[String]): Unit = {def max(a:Int,b:Int):Int = {
if(a > b) return a;
else return b;
}//def max(a:Int,b:Int):Int = {
//if(a > b)a else b;
//}val result : Int = max(100,20);
println(result)
}
}
文章图片
递归方法
递归方法必须指定返回值类型
def fun(num:Int):Int = {
if(num == 1) return 1
else return num * fun(num - 1)
}println(fun(5))
有参数默认值的方法
def fun(a:Int=10,b:Int=20) = {
a + b;
}
println(fun()) // 不覆盖
println(fun(100,300)) // 全部覆盖
println(fun(100)) // 覆盖a
println(fun(b = 50)) // 覆盖b
文章图片
可变长参数的方法
def fun(s:String*)={
s.foreach(elem=>{println(elem)})// 两种输出方式
for(string <- s) println(string)
}fun("zhang","liu","wang")
文章图片
匿名函数
=>就是匿名函数
def fun = (a:Int,b:Int)=>{
a+b
}println(fun(1,6))
文章图片
嵌套
def fun(a:Int): Int ={ def fun1(b:Int): Int ={
if(b == 1) 1
else b * fun1(b - 1)
} fun1(a)}println(fun(5))
文章图片
偏应用函数
def show(date:Date,log:String)={
println(s"date is $date,log is $log")// s $引用外部的属性
}def fun = show(date = new Date(),_:String) // _ 占位符
fun("a")
fun("b")
fun("c")
文章图片
方法参数是函数
类型指定(Int,Int) =>Int
def fun(f:(Int,Int)=>Int,s:String):String={
val res:Int = f(100,200)
res + ""+s
}val result = fun((a:Int,b:Int)=>{a*b},"scala")
println(result)
文章图片
返回值是函数
def fun(s:String):(String,String)=>String={
def fun1(s1:String,s2:String):String={
s + s1 + s2
} fun1
}println(fun("zhang")("liu","wang"))
文章图片
方法参数和返回值都是函数
def fun(f:(Int,Int)=>Int,s:String):(String,String)=>String={
val a:Int = f(100,200) def fun1(s1:String,s2:String):String={
s1+s2+s+a.toString
} fun1
}val res = fun((a:Int,b:Int)=>{a+b},"hello")("zhang","kun")
println(res)
文章图片
柯里化函数
def fun(a:Int,b:Int)(c:Int,d:Int)={
a+b+c+d
}
println(fun(1,2)(3,4))
文章图片
4.字符串
object StringTest {
def main(args: Array[String]): Unit = {
val s = "zhang"// 普通字符串
val s1 = "zhang1"val sb = new StringBuffer();
// 可变字符串
sb.append(s).append("liu")println(sb)val i = s.compareTo(s1)// compareTo
println(i)println(s1.charAt(1)) // 索引val chars = s.toCharArray // 字符串转数组
chars.foreach(c=>{print(c+" ")})}
}
文章图片
5.数组
object ArrayTest {
def main(args: Array[String]): Unit = {val array = Array[String]("ab","bc") // 直接赋值
array.foreach(s=>{print(s + " ")})
println()val array2 = new Array[Int](3) // 先声明再赋值,new不可以省略
array2(0) = 2
array2(1) = 3
array2(2) = 10
array2.foreach(num=>{print(num + " ")}) // 遍历数组
println()val array3 = new Array[Array[Int]](3) // 二维数组 三行
array3(0) = Array[Int](1,2,3,8)
array3(1) = Array[Int](1,6,2)
array3(2) = Array[Int](8,12,9)array3.foreach(arr=>{arr.foreach(num=>{print(num+" ")});
println()}) // 遍历二维数组var myList1 = Array(1.9, 2.9, 3.4, 3.5)// 合并数组
var myList2 = Array(8.9, 7.9, 0.4, 1.5)
var myList3 =Array.concat(myList1, myList2)
// 输出所有数组元素
for ( x <- myList3 ) {
print( x + " ")
}
println()var myArr = Array.range(10,20)// 区间数组
myArr.foreach(num=>{print(num+" ")})}
}
文章图片
6.集合 List
object ListTest {
def main(args: Array[String]): Unit = {val list = List[String]("hello_java","zhang_kun_song")
list.foreach(s=>{print(s+" ")}) // 遍历集合
println()
println(list(0)) // 通过索引获取 val list3 = ListBuffer[Int]() // 可变List
list3.append(1,2,3)val list1 = list.map(s => { // 对集合中的每一个元素分割,得到的是泛型为数组的集合
s.split("_")// [hello,java] [zhang,kun,song]
})
list1.foreach(arr=>{arr.foreach(s=>{print(s+" ")});
println()})val list2 = list.flatMap(s => {
s.split("_") // [hello] [java] [zhang] [kun] [song]
})
list2.foreach(arr=>{print(arr + " ")})
}
}
文章图片
Set
object SetTest {
def main(args: Array[String]): Unit = {
val set = Set[Int](1,2,2,2,3,4,5)
val set1 = Set[Int](4,5)set.foreach((num)=>print(num+" "))// set有去重功能
println()val ints = set.intersect(set1) // 集合差集 也可以 set & set1
val ints1 = set.diff(set1) // 差集val set2 = mutable.Set[Int](1,2,3)// 可变set
set2.+=(4)
set2.foreach((num) =>{print(num+" ")})
}
}
文章图片
Map
object MapTest {
def main(args: Array[String]): Unit = {
val map = Map[String,Int]("aa"->20,("b",30),("b",40));
val value = https://www.it610.com/article/map.get("aa").get // 获取value 20for(elem <- map){// 遍历map
println(elem)
}map.foreach(kv=>{ // 遍历集合
println(kv)
})val keys = map.keys // 获取所有键值keys.foreach(key=>{// 遍历key获取value
val value1 = map.get(key).get
println(s"key == $key,value = https://www.it610.com/article/$value1")
})val values = map.values // 获取所有valueval map1 = Map[String,Int]("aa"->20,("b",30),("c",40));
val map2 = Map[String,Int]("aa"->30,("b",40),("c",50));
val map3 = map1.++(map2)// map2替换map1
val map4 = map1.++:(map2)// map1替换map2val map5 = mutable.Map[String,Int]()// 可变map
map5.put("song",24)}
}
文章图片
object TupleTest {
def main(args: Array[String]): Unit = {
// 元组可以存不同类型的元素
val tuple = new Tuple1("zhang")
val tuple2 = new Tuple2("zhang",'C')
val tuple4 = new Tuple4("zhang", false, 'C', 16)val value = https://www.it610.com/article/tuple2._1 // ._xx取值
println(value)val value1 = tuple4._4
println(value1)val iterator = tuple4.productIterator// 遍历,只能先拿到迭代器
iterator.foreach(value=>{println(value)})}
}
文章图片
四.常用语法
1.Trait Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大
与接口不同的是,它还可以
定义属性和方法的实现
一般情况下Scala的类只能够继承单一父类,但是如果是 Trait(特征) 的话就可以继承多个,从结果来看就是实现了多重继承
Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait
trait Audi{
val name = "Audi"
def runAudi(time:Int)={
println(name+"running....."+time)
}
}trait Benz{
val name1 = "Benz"
def runBenz(time:Int)={// 实现的方法
println(name1+"running....."+time)
}def recreate():String// 未实现的方法
}class Car extends Audi with Benz {// 继承第一个用extends,第二个用with
override def recreate(): String = {
"recreate.."
}
}object TraitTest {
def main(args: Array[String]): Unit = {
val car = new Car
car.runBenz(10)
car.runAudi(20)
}}
文章图片
2.Match 一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式
case _ 什么都不匹配
可以匹配类型,也可以匹配值
object MatchTest {
def main(args: Array[String]) {
println(matchTest("two"))
println(matchTest("test"))
println(matchTest(1))
println(matchTest(6))
println("偏函数"+myTest("ooo"))}
def matchTest(x: Any): Any = x match {
case 1 => "one"
case "two" => 2
case y :Int => "scala.Int"// 匹配Int类型
case _ => "no match" // case _ 什么都不匹配,类似 switch 中的 default
}def myTest:PartialFunction[String,Int] = {// 偏函数相比match没有match了,匹配String,返回Int
case "abc" => 22
case "bcd" => 66
case _ => 84
}
}
文章图片
3.样例类 使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配,默认有get和set(对val类型)方法
object CaseClass {
def main(args: Array[String]) {
val alice = new Person("Alice", 25)
val bob = new Person("Bob", 32)
val charlie = new Person("Charlie", 32)for (person <- List(alice, bob, charlie)) {
person match {
case Person("Alice", 25) => println("Hi Alice!")
case Person("Bob", 32) => println("Hi Bob!")
case Person(name, age) =>
println("Age: " + age + " year, name: " + name + "?")
}
}
}
// 样例类
case class Person(name: String, age: Int)
}
文章图片
4.隐式值与隐式参数
- 用implicit修饰的值就是隐式值
- 用implicit修饰参数就是隐式参数,注意,如果方法中
部分参数
是隐式参数,必须使用柯里化的方式
当调用方法时,不必手动传入方法中隐式参数,Scala会自动在作用域内寻找隐式值并自动传入,
所以在一个作用域内不能定义多个类型一样的隐式值
object ImplicitTrans {
def main(args: Array[String]): Unit = {
implicit val name:String = "zhang"// implicit声明隐式值柯里化的方式def sayName(age:Int)(implicit name:String) ={//
println(s"$name is student... age = $age")
}sayName(10)}
}
文章图片
5.隐式转换函数 作用
实现类中方法的共享
class Red{
def sayWho()={
println("Red Red Red")
}
}class Green{}object ImplicitTest {implicit def greenToRed(green: Green):Red = {// 隐式函数
new Red
}def main(args: Array[String]): Unit = {
val green = new Green
green.sayWho()
}}
文章图片
上面的例子中,创建了green对象,但我想用Red类中的方法,于是我就声明一个隐式函数,传入green对象,返回一个red对象,就可以调用了
注意:相同作用域内,不可以定义相同的传入参数和返回类型相同的隐式函数
6.隐式类
class Dog{}
object ImplicitClass {
implicit class Animall(dog: Dog){
def sayName(): Unit ={
println("dog隐式类...")
}
}def main(args: Array[String]): Unit = {
val dog = new Dog
dog.sayName// 创建了一个dog对象
}
}
创建了一个dog对象,调用了sayName方法,但实际类中是没有这个方法的,于是就去找有没有一个隐式类,参数是Dog类型的,有的话就可以调用里面的方法
推荐阅读
- 大数据|数据、信息和知识的区别和联系
- 大数据|控制论,计算机设计和思想会议
- 人工智能|十年AI谁“最能打”(AI 2000榜单(何恺明最佳论文“刷”状元,谷歌机构排名第一...))
- 人工智能|十年AI谁“最能打”(何恺明最佳论文“刷”状元,谷歌机构排名第一)
- 人工智能|何恺明霸榜!近10年里的具有影响力的一作(年轻)AI学者大盘点!谷歌机构排名第一!...
- 开发工具|TensorFlow1.0正式发布,AI圈“互怼”那些事儿 | AI科技评论周刊
- 人脸识别|从人脸识别到唇语识别,图像识别技术发展现状
- 百度|2021中国低/无代码平台投融资趋势报告( 融资规模近15亿,估值近70亿,马太效应将愈演愈烈...)
- 大数据|R语言——数据格式和数据读取