Scala使用
1、scala构造方法。定义方法。重载构造方法
package com
object Demo03ScalaClass {
def main(args: Array[String]): Unit = {
val stu1: Stu = new Stu("01", "王五", 18)
println(stu1._id)
println(stu1._name)
println(stu1._age)
stu1.printInfo()
val stu2: Stu = new Stu("02", "小宋", 18, "学习委员")
println(stu2._pro)
}
}
// 由{}括起来的就是Scala默认的构造方法
class Stu(id:String,name:String,age:Int){
// 在定义属性的时候即赋值
val _id:String=id
val _name:String=name
val _age:Int=age
var _pro:String=_ //如果在定义属性的时候未赋值 则先用下划线替代
//定义方法
def printInfo(): Unit = {
println(s"Stu(${_id},${_name},${_age})")
}
//重载构造方法
def this(id:String,name:String,age:Int,pro:String)={
// 在重载的构造方法的第一行代码必须调用默认的构造方法
this(id,name,age)
_pro=pro
}
}
2、scala继承、多态
package com
object Demo04ScalaExtend {
// def stuJumpTwice(stu: Student): Unit = {
// stu.jump()
// stu.jump()
// }
//
// def teaJumpTwice(tea: Teacher): Unit = {
// tea.jump()
// tea.jump()
// }
// 多态:父类的引用指向子类对象
def personJumpTwice(per: Person): Unit = {
per.jump()
per.jump()
}
def main(args: Array[String]): Unit = {
val stu1: Student = new Student("001", "小明同学", 20, 560)
stu1.learning()
stu1.eat()
stu1.jump()
println(stu1._score)
personJumpTwice(stu1)
val teacher1 = new Teacher("1000001", "张老师", 25, "理科一班")
teacher1.teaching()
teacher1.eat()
teacher1.jump()
println(teacher1._clazz)
personJumpTwice(teacher1)
}
}
class Person(id: String, name: String, age: Int) {
val _id: String = id
val _name: String = name
val _age: Int = age
def eat(): Unit = {
println("人类饿了都会吃饭")
}
def jump(): Unit = {
println("人类除了吃还会跳")
}
}
// 继承关键字:extends
// 注意:子类在继承父类的时候需要将父类构造方法所需要的参数进行传递
class Student(id: String, name: String, age: Int, score: Int) extends Person(id, name, age) {
val _score: Int = score
def learning(): Unit = {
println("学生会学习")
}
override def jump(): Unit = {
println("学生除了吃还会跳")
}
}
class Teacher(id: String, name: String, age: Int, clazz: String) extends Person(id, name, age) {
val _clazz: String = clazz
def teaching(): Unit = {
println("老师会上课")
}
override def jump(): Unit = {
println("老师除了吃还会跳")
}
}
3、scala样例类
package com
object Demo05CaseClass {
def main(args: Array[String]): Unit = {
val s1: CaseStudents = new CaseStudents("01", "李四", 22)
println(s1.id)
println(s1.name)
println(s1.age)
val s2: CaseStudents = CaseStudents("02", "王五", 21)
println(s2.id)
println(s2.name)
println(s2.age)
s2.age = 25
println(s2.age)
println(s1)
println(s2)
val t1: CaseTeachers = new CaseTeachers("1", "2", "3")
println(t1)
}
}
// 样例类
/*
1、样例类对象在创建时不需要使用new关键字
2、样例类对象的属性默认都是由val修饰的,如果需要修改则在定义时需要用var修饰
3、样例类在编译时默认会给每个属性加上get方法,如果有var修饰的属性则有set方法
4、样例类默认会实现序列化接口,所以可以在网络中传输
5、样例类默认会重写toString方法,打印时可以直接将所有的属性输出
*/
case class CaseStudents(id: String, name: String, var age: Int)
case class CaseTeachers(y:String,o:String,u:String)
4、Scala伴生对象
package com
object Demo06Apply {
def main(args: Array[String]): Unit = {
val car1: Car = new Car("奔驰", "黑色")
val car2: Car = Car.apply("奥迪", "白色")
val car3: Car = Car("宝马", "蓝色") // 默认会调用apply方法
}
}
class Car(brand: String, color: String) {
val _brand: String = brand
val _color: String = color
}
// 伴生对象
object Car {
def apply(brand: String, color: String): Car = new Car(brand, color)
}
5、函数
package com
object Demo07Func1 {
def print(): Unit = {
println("Object print")
}
// 实现两个数的相加,一个数是Int类型,另一个是String类型,最后返回Int类型
/**
* def 关键字
* func1 函数名
* i:Int 参数名为i,类型为Int
* s:String 参数名为s,类型为String
* 多个参数之间用逗号分割
* :Int= 返回值类型为Int
* {} 函数体
*/
def func1(i: Int, s: String): Int = {
return i + s.toInt
}
def func1_1(i: Int, s: String): Int = {
i + s.toInt
}
def func1_2(i: Int, s: String): Int = i + s.toInt
def func1_3(i: Int, s: String) = i + s.toInt
def func2() = {
100 + 200
}
def func2_4 = 100 + 200 // 这是一个函数,这不是变量
/**
* 函数的省略规则:
* 1、最后一行代码默认会作为函数的返回值,所以return关键字可以省略
* 2、如果代码只有一行,花括号可以省略
* 3、返回值类型可以自动推断故能省略
* 4、如果函数没有参数,括号可以省略
*/
def main(args: Array[String]): Unit = {
/*
函数可以在哪里定义?
在Scala中可以在任意位置定义函数,注意在函数内部也能定义函数
*/
def func01(): Unit = {
println("main 函数中的 func01")
}
println(func1(100, "200"))
println(func1_1(100, "200"))
println(func1_2(100, "200"))
println(func1_3(100, "200"))
println(func2())
println(func2_4)
}
}
6、函数类型与匿名函数类型
package com
object Demo08Func2 {
def main(args: Array[String]): Unit = {
/**
* 面向对象编程:将对象传来传去,将对象作为参数 或者是 返回值,需要考虑类型的限制
* 面向函数编程:将函数传来传去,将函数作为参数 或者是 返回值,需要考虑类型的限制
*
* 函数式编程(面向函数、高阶函数):
* 1、以函数作为参数
* 2、以函数作为返回值
*
* 函数的类型怎么描述?
* 1、跟def关键字无关
* 2、跟函数名无关
* 3、跟函数体无关
* 4、跟参数名无关
* 5、跟函数的参数(参数类型,个数,顺序)以及返回值类型有关
* 怎么具体描述一个函数的类型?
* 参数的类型=>返回值的类型
*/
// 这是一个(参数类型为Int和String,返回值类型为Int)函数
// (Int,String)=>Int
def func01(int: Int, str: String): Int = int + str.toInt
// (Int,String)=>Int
def func02(int: Int, str: String): Int = int + str.toInt + 100
// (Int,Int)=>Int
def func03(int1: Int, int2: Int): Int = int1 + int2
// (Int, String) => Int) => Unit
def funcX(func: (Int, String) => Int): Unit = {
println(func(100, "200"))
}
def func05(i: Int): String = {
(i + 100).toString
}
def func06(i: Int): String = {
i.toString
}
def funcXX(func: Int => String): Unit = {
println("funcXX:" + func(100))
}
funcX(func01)
funcX(func02)
// funcX(func03)
funcXX(func05)
// 匿名函数
// 定义:匿名函数所需要的参数 => 匿名函数的函数体
// Int => Int
// i: Int => i * i
// 匿名函数无法直接调用 主要用于作为函数传递给另外一个函数
// 匿名函数实际上是可以拥有名字的
val anonymousFunc: (Int, String) => Int = (i: Int, s: String) => {i + s.toInt + 200}
println(anonymousFunc(100, "100"))
funcX(anonymousFunc)
funcX((i: Int, s: String) => {
i + s.toInt + 200
})
/**
* 匿名函数的省略:
* 1、如果代码只有一行,花括号可以省略
* 2、如果匿名函数是作为另外一个函数的参数传递,则匿名函数的参数的类型可以省略
* 3、如果参数只有一个,则括号可以省略 (推荐省略到第三步即可)
* 4、如果参数只被使用了一次,则可以用下划线替代
*/
funcX((i: Int, s: String) => i + s.toInt + 200)
funcX((i, s) => i + s.toInt + 200)
// 使用匿名函数代替func05
funcXX(i => (i + 100).toString)
// 使用匿名函数代替func06
funcXX(_.toString)
}
}
7、scala中的次方、foreach函数
package com
object Demo09Func3 {
def main(args: Array[String]): Unit = {
// 面向函数编程:以函数作为参数的应用
// 创建一个数组
val arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7)
// 对arr中的每个元素都做一次 次方 再打印
// 用Java的思想
var i: Int = 0
while (i < arr.length) {
println(arr(i) * arr(i) * arr(i))
i += 1
}
// 使用for循环遍历
for (elem <- arr) {
println(elem * elem * elem)
}
// 用Scala的思想:采用了面向函数编程的思想
// Int => Unit
def printInt(int: Int): Unit = {
println(int)
}
/**
* foreach函数:需要接受一个参数f
* 参数f: 函数类型 Int=>U
*
* println: Any=>U
* 因为Any是任何类型的基类,包含了Int,所以println函数可以作为foreach所需的参数f传入
*/
arr.foreach(println)
arr.foreach(println)
def printPow2(int:Int):Unit={
println(int * int)
}
arr.foreach(printPow2)
//借助匿名函数进行简写
arr.foreach(i=>println(i*i))
arr.foreach(i=>println(i*i*i))
}
}
8、函数柯里化、偏应用函数
package com
object Demo10Func4 {
//以函数作为返回值时需要手动指定外层函数的返回值类型
def func1(int:Int):String => Int = {
def func1_1(str:String):Int={
int+str.toInt
}
func1_1
}
//上面的简写
def func2(int:Int)(str:String):Int={int+str.toInt}
// 函数柯里化:将有N个参数的函数-->变成N个只有一个参数的函数
def func3(i1: Int, i2: Int, i3: Int): Int = {
i1 + i2 + i3
}
//柯里化
def func4(i1:Int)(i2:Int)(i3:Int):Int = {
i1+i2+i3
}
//偏应用函数:将有N个参数的函数-->N-M个参数的函数,M为固定的参数的个数
def func5(a:Int,b:Int):Double = {
Math.pow(a,b)
}
def func6(a:Int,b:Int=2):Double={
Math.pow(a,b)
}
def main(args: Array[String]): Unit = {
//面向函数编程:以函数作为返回值
val stringToInt: String => Int = func1(10)
val i:Int=stringToInt("20")
println(i)
// 合并调用
println(func1(10)("20"))
// 对简写形式的调用
println(func2(10)("20"))
}
}
9、Java中的wordCount和scala中的wordCount
java
package com;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class Demo02WordCountJava {
public static void main(String[] args) throws IOException {
// 使用Java代码统计words.txt中每个单词的数量
// 读取文件
BufferedReader br = new BufferedReader(new FileReader("bigdata19-scala/data/words.txt"));
String line = null;
// 构建Map用于存储最后的结果
HashMap<String, Integer> wordCountMap = new HashMap<>();
while ((line = br.readLine()) != null) {
// 对每一行数据进行处理
// java,spark,java,hadoop
for (String word : line.split(",")) {
// 如果word第一次出现 则放入Map中 并将value置为1
if (!wordCountMap.containsKey(word)) {
wordCountMap.put(word, 1);
} else {
// 如果word不是第一次出现 则将其value取出来加1
Integer oldValue = wordCountMap.get(word);
wordCountMap.put(word, oldValue + 1);
}
}
}
for (Map.Entry<String, Integer> kv : wordCountMap.entrySet()) {
System.out.println(kv.getKey() + "," + kv.getValue());
}
}
}
scala
package com
import scala.io.Source
object Demo11WordCountScala {
def main(args: Array[String]): Unit = {
// 1、读取文件
val lines: List[String] = Source.fromFile("bigdata19-scala/data/words.txt").getLines().toList
lines.foreach(println)
// 2、将每个单词切分出来
// map可以作用在每一行数据上,与foreach的区别在于 map方法有返回值 foreach方法没有返回值
// val newLinesList: List[Array[String]] = lines.map(_.split(","))
// newLinesList.foreach()
// flatMap 可以作用在每一行数据上,需要一个返回值类型为集合类 的值
val wordsList: List[String] = lines.flatMap(_.split(","))
//3.按单词进行分组
//不简写的方式
// def grp(word:String):String={
// word
// }
val words: Map[String, List[String]] = wordsList.groupBy(word => word)
//4.统计每个单词的数量
//不简写
// def wordCount(kv:(String,List[String])):String={
// val word = kv._1
// val count = kv._2.length
// word + "," +count
// }
// words.map(wordCount).foreach(println)
words.map(kv =>{//mao需要的类型是元祖
val word =kv._1
val count=kv._2.length
word + "," + count
}).foreach(println)
//链式调用
Source
.fromFile("bigdata19-scala/data/words.txt")
.getLines()
.toList
.flatMap(_.split(","))
.groupBy(word=>word)
.map(kv=>{
val word=kv._1
val count=kv._2.length
word + "," + count
})
.foreach(println)
}
}
10、scala中的List
package com
object Demo12List {
def main(args: Array[String]): Unit = {
/**
* List列表
* 特点:有序、元素可以不唯一、不可变,一般用于有序地存储同类型的数据
*/
val list: List[Int] = List[Int](1, 2, 3, 4, 4, 4, 4, 5, 6, 7, 8, 8, 9)
println(list)
// List常见的方法
println(list.max) // 最大值
println(list.min) // 最小值
println(list.sum) // 对所有元素求和
println(list.length) // 元素的个数
println(list.size) // 元素的个数
println(list.head) // 返回第一个元素
println(list.tail) // 返回除第一个元素以外的元素
println(list.take(3)) // 返回前n个元素
println(list.isEmpty) // 判断是否为空
println(list.contains(8)) // 判断元素是否存在
println(list.contains(10))
println(list.last) // 返回最后一个元素
// 通过下标取元素
println(list(7))
// 不能够直接进行修改,List默认是不可变的
// list(7) = 55
println(list)
// 常见的操作
// map、flatMap、foreach、groupBy、sort相关、filter
/**
* foreach方法需要接受一个参数f
* 参数f:Int=>Unit
* 将List中的每一个元素依次传给f,没有返回值
*/
list.foreach(println)
/**
* map方法需要接受一个参数f
* 参数f:Int=>B (B表示返回值类型自定义)
* 将List中的每一个元素依次传给f,有返回值
* 最终会返回一个新的List,新的List中每个元素的类型为B
*/
// 对List中的每个元素 对%3
val list2: List[Double] = list.map(i => (i % 3).toDouble)
list2.foreach(println)
/**
* filter方法需要接受一个参数p
* 参数p:Int=>Boolean
* 将List中的每一个元素依次传给p
* 最终会根据p返回的布尔值进行过滤
* 如果是true则保留元素
* 否则是false则过滤元素
* 最终会返回过滤后的新的List
*/
// 将奇数过滤出来
list.filter(i => i % 2 == 1).foreach(println)
list.filter(i => i % 2 == 0).foreach(println)
val list3: List[String] = List("java,scala,python", "hadoop,hive,hbase")
/**
* flatMap方法需要接受一个参数f
* 参数f:String=>GenTraversableOnce
* GenTraversableOnce: 可以遍历的类型
* 将List中的每一个元素依次传给f,f需要返回一个可以遍历的类型(例如:List、Array、Set等)
* 最后会将返回的 可以遍历的类型 进行展开 (扁平化处理)
* 一般用于展开数据
*/
list3.flatMap(_.split(",")).foreach(println)
val stuList = List[StuL](
StuL("001", "张三1", 20, "文科一班"),
StuL("002", "张三2", 21, "文科一班"),
StuL("003", "张三3", 22, "理科一班"),
StuL("004", "张三4", 22, "理科一班")
)
/**
* groupBy方法:指定一个字段进行分组
* 需要接收一个参数f
* 参数f: StuL=>K (K表示最好是基于输入的数据进行转变的到的非空类型,也可以自己指定)
* 最终会将属于同一组的数据放到一个Map中(key:指定的分组字段,value:属于同一组的数据构成的List)
* 最终会的一个Map
*/
// 按照班级分组
val grpMap: Map[String, List[StuL]] = stuList.groupBy(s => s.clazz)
grpMap.foreach(println)
/**
* sort排序相关的方法
*/
// 指定一个字段进行排序 默认升序
stuList.sortBy(s => s.age).foreach(println)
stuList.sortBy(s => -s.age).foreach(println)
val list5: List[Int] = List(1, 3, 2, 45, 6, 7, 9, 2)
val sortedList: List[Int] = list5.sorted
println(sortedList)
/**
* 指定一个排序规则 类似Java中的compareTo
* sortWith:需要接受一个参数lt
* 参数lt: (StuL,StuL) => Boolean
*/
def cp(s1: StuL, s2: StuL): Boolean = {
var flag: Boolean = false
if (s1.age == s2.age) {
if (s1.id > s2.id) {
flag = true
}
}
flag
}
stuList.sortWith(cp).foreach(println)
// 可变的List --> ListBuffer
// 可变:可以任意的增加删除修改元素
val lb1: ListBuffer[Int] = ListBuffer[Int](1, 2, 3, 3, 3, 4, 5, 6, 7, 8, 8)
println(lb1)
// 可变的一些操作
// 增加
lb1.append(10) // 将元素追加到原有的ListBuffer的尾部
println(lb1)
lb1.insert(10, 9) // 指定位置进行增加
println(lb1)
lb1 += 11
println(lb1)
// 删除
val lb2: ListBuffer[Int] = lb1.drop(5) // 删除指定个数的元素并返回新的ListBuffer
println(lb2)
lb1.remove(5)
lb1.remove(2, 2)
println(lb1)
lb1 -= 6
println(lb1)
// 修改
lb1.update(3, 4)
println(lb1)
lb1(4) = 6
println(lb1)
}
case class StuL(id: String, name: String, age: Int, clazz: String)
}
11.scala中的元祖
package com
object Demo13Tuple {
def main(args: Array[String]): Unit = {
// Tuple元组:不可变的、有序、元素可以不唯一、最大长度为22
val t1: Tuple1[Int] = Tuple1(1)// 构建一个一元组
println(t1)
// 可以通过“下标”取出元素
val t2: (Int, Int) = Tuple2(1, 2)
println(t2._2)
val t3:(Int,Int,Int)=(1,2,3)
println(t3._3)
}
}
12.scala中的map
package com
import scala.collection.mutable
object Demo14Map {
def main(args: Array[String]): Unit = {
//map:每个元素都是k-v格式、不可变的、无序的、key不能重复、key必须是不可变类型
val map1: Map[String, String] = Map[String, String](("k1", "v1"), ("k2", "v2"), ("k3", "v3"))
println(map1)
//通过key获取value
val str: String = map1("k2")
println(str)
/**
* Option类型:拥有两个子类Some、None
* 当元素存在时 会返回Some
* 如果不存在 则会返回None
* 一般用于一些可能有也可能没有的情况
*/
val maybeString: Option[String] = map1.get("k2")
println(maybeString)
println(maybeString.get)
val maybeString1: Option[String] = map1.get("k4")
println(maybeString1)
val str1: String = map1.getOrElse("k3", "如果没有取到则返回默认值")
val str2: String = map1.getOrElse("k4", "如果没有取到则返回默认值")
println(str1)
println(str2)
def m(kv:(String,String)):String={
kv._2
}
/**
* f:((String,String)) => B 只需要一个参数接收,参数的类型为二元组
* f:(String,String) => 需要两个参数,类型分别为String、String
*/
map1.map(kv=>kv._2).foreach(println)
//可变的Map -->HashMap
val hashMap: mutable.Map[String, String] = mutable.HashMap(("k1", "v1"), "k2"->"v2", ("k4", "v4"))
println(hashMap)
//增加元素
hashMap.put("k3","v3")
println(hashMap)
hashMap("k5")="v5"
println(hashMap)
hashMap.+=("k6"->"v6")
//删除元素
hashMap.remove("k1")
hashMap.-=("k2")
println(hashMap)
//修改元素
hashMap("k4")="vv4"
hashMap.put("k5","vv5")
println(hashMap)
}
}
13.Scala中的Set
package com
import scala.collection.mutable
object Demo15Set {
def main(args: Array[String]): Unit = {
// Set集合:不可变的、无序的、元素不能重复、会自动对重复的元素进行去重
// 一般用于集合之间的运算:交集、并集、差集等等
val set1: Set[Int] = Set[Int](1, 2, 3, 3, 4, 4, 4, 5, 6, 6, 7, 8)
println(set1)
// 集合的运算
val set2: Set[Int] = Set(1, 2, 3, 4, 5, 6)
val set3: Set[Int] = Set(4, 5, 6, 7, 8, 9)
println(set2 & set3)
println(set2 | set3)
println(set2.diff(set3))//diff求差集
println(set3.diff(set2))
// 可变的Set
val hashSet1: mutable.HashSet[Int] = mutable.HashSet(1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 7)
println(hashSet1)
hashSet1.add(10)
hashSet1.add(1)
hashSet1.add(1)
hashSet1.add(1)
println(hashSet1)
hashSet1.remove(6)
println(hashSet1)
// 修改:先删除、再添加
}
}
14.Scala中的Match(模式匹配)
package com
object Demo16Match {
def main(args: Array[String]): Unit = {
/**
* match 模式匹配,类似Java中的switch
*
* Java中的模式匹配可以匹配:
* 1、基本数据类型
* 2、字符串
* 3、枚举
*
* Scala中的模式匹配可以匹配:
* 1、基本数据类型
* 2、字符串
* 3、枚举
* 4、类型
* 5、样例类对象
*/
// 1、基本数据类型的匹配
val i:Int=18
i match{
case 10=>//花括号可以省略
println(10)
case 20=>
println(20)
case _=>
println("无法匹配")//相当于java中的default
}
//2、字符串匹配
val str: String = "c"
str match{
case "java" => println("java")
case "scala" => println("scala")
case "python" => println("python")
case _ => println("没有匹配到的默认值")
}
// 3、枚举类型的匹配
val monday: MyEnums.Value = MyEnums.Monday
monday match {
case MyEnums.Monday => println(MyEnums.Monday)
case MyEnums.Tuesday => println(MyEnums.Tuesday)
case MyEnums.Wednesday => println(MyEnums.Wednesday)
case MyEnums.Thursday => println(MyEnums.Thursday)
case MyEnums.Friday => println(MyEnums.Friday)
case MyEnums.Saturday => println(MyEnums.Saturday)
case MyEnums.Sunday => println(MyEnums.Sunday)
}
// 4、类型的匹配
val v1: Any = 100
v1 match {
case s: String => println(s"匹配的值${s}是String类型")
case i: Int => println(s"匹配的值${i}是Int类型")
}
// 5、样例类对象的匹配
case class StuMatch(id: String, name: String, age: Int)
val stu1: StuMatch = StuMatch("001", "zs", 20)
val stu2: StuMatch = StuMatch("002", "ls", 22)
stu2 match {
// 该样例类对象必须保证属性完全一致才能匹配上
case StuMatch("001", "zs", 20) => println("这是zs")
case StuMatch("002", "ls", 22) => println("这是ls")
}
// 模式匹配在Map集合中的应用
val map1: Map[String, String] = Map("k1" -> "v1", "k2" -> "v2", "k3" -> "v3")
// 手动实现getOrElse
// Scala中的模式匹配可以有返回值
val opt: Option[String] = map1.get("k1")
val returnVal: String = opt match {
case Some(v) =>
println(s"对应的value为${v}")
v
case None => println("Key不存在")
"默认值"
}
println(returnVal)
val r = if (10 > 9) {
"ok"
} else {
"no"
}
println(r)
// 模式匹配在map方法中的应用:可以让代码更加简洁,方便提取一些嵌套的数据
val stuList: List[(String, (String, (Int, String)))] = List(
("001", ("zs1", (21, "文科一班"))),
("002", ("zs2", (22, "文科二班"))),
("003", ("zs3", (23, "文科三班"))),
("004", ("zs4", (24, "文科四班")))
)
// 将stuList中的嵌套的数据展开
// ("001", ("zs1", (21, "文科一班"))) => 字符串: 001,zs1,21,文科一班
stuList
.map(kv => {
val id: String = kv._1
val name: String = kv._2._1
val age: Int = kv._2._2._1
val clazz: String = kv._2._2._2
s"$id,$name,$age,$clazz"
})
.foreach(println)
stuList
.map{
case (id:String, (name:String, (age:Int, clazz:String))) =>
s"$id,$name,$age,$clazz"
}.foreach(println)
}
}
object MyEnums extends Enumeration{
val Monday: MyEnums.Value = Value("Mon.")
val Tuesday: MyEnums.Value = Value("Tues.")
val Wednesday: MyEnums.Value = Value("Wed.")
val Thursday: MyEnums.Value = Value("Thur.")
val Friday: MyEnums.Value = Value("Fri.")
val Saturday: MyEnums.Value = Value("Sat.")
val Sunday: MyEnums.Value = Value("Sun.")
}
15.scala中的空(Null、None、Unit、Nil、Nothing)
package com
object Demo17NoneNilNullNothingUnit {
// Null null Nil Nothing None Unit
def main(args: Array[String]): Unit = {
// 1、Null and null(用的时候可以把Null看做一个类型,null看做Null的对象)
// Null是一个trait特征
// null是Null的实例
def tryit(thing: Null): Unit = {
println("That worked!")
}
// tryit("hey")
val someRef: String = null
// tryit(someRef)
tryit(null)
val nullRef: Null = null
tryit(nullRef)
// 2、Nil 空的列表
val nil: Nil.type = Nil
println(nil)
println(nil.length)
// 3、Nothing
/**
* trait :scala中的接口 但又像抽象类
* Nothing是另一个trait。它继承了Any类。Any是整个Scala类型系统的超类。
* Any可以引用对象类型以及诸如普通的旧整数或双精度的值。
* Nothing是一切类型的子类。
* Nothing没有具体的实例。
* Nothing是List的子类,它是String的子类,它是Int的子类型,它是YourOwnCustomClass的子类。
*/
val ints: List[Any] = List[Int](1, 2, 3, 4, 5)
val emptyStringList: List[Stu] = List[Nothing]()
val f:List[Car] = List[Nothing]()
val emptyIntList: List[Int] = List[Nothing]()
// val emptyStringList: List[String] = List[Nothing]("abc")
// 4、None
/**
* 当你写一个函数,遇到没有什么实用价值的情况时,你会怎么做?
* 通常有几种方法来处理它:
* 1、你可以返回null,但是这会导致问题。
* 如果调用者不希望得到null,那么当他尝试使用它时可能会面临NullPointerException
* 否则调用者必须检查null
* 一些函数不会返回null,但有些函数可能会。
* 作为一个调用者,他不知道那些函数会返回null 哪些不会。
*
* 2、使用throws关键字,作为异常抛出。
* 需要用try / catch处理
* 通常希望在真正发生异常的情况下才使用try/catch
* 而不仅仅是为了处理一个普通的无结果的情况
*
* 3、Scala中的方式。
* 如果你想返回一个字符串
* 但你知道你可能无法返回一个合理的值
* 你可以返回一个Option[String]
*/
val s:String = null
if(s!=null){
s.split(",")
}
def getAStringMaybe(num: Int): Option[String] = {
if (num >= 0) {
Some("A positive number!")
}
else {
None
} // A number less than 0? Impossible!
}
val num: Int = 100
getAStringMaybe(num) match {
case Some(str) => println(str)
case None => println("No string!")
}
// 5、Unit 相当于Java中的void,表示函数不返回任何值
}
}
16、Scala中的trait
package com
object Demo18Trait {
def main(args: Array[String]): Unit = {
val q:Q = new Q(10, 20)
println(q.isEqual(q._q))
}
}
trait MyTrait1 {
// Scala中的特征 类似Java中的接口 但有一点像抽象类
// 可以在特征中直接定义变量
val i: Int = 10
// 定义抽象的方法
def isEqual(int: Int): Boolean
// 定义具体的方法
def isNotEqual(int: Int): Boolean = {
!isEqual(int)
}
}
trait MyTrait2 {
// Scala中的特征 类似Java中的接口 但有一点像抽象类
// 可以在特征中直接定义变量
val i2: Int = 20
// 定义抽象的方法
def isEqual2(int: Int): Boolean
// 定义具体的方法
def isNotEqual2(int: Int): Boolean = {
!isEqual2(int)
}
}
class P(p: Int) {
val _p: Int = p
}
class Q(p: Int, q: Int) extends P(p) with MyTrait1 with MyTrait2 {
val _q: Int = q
override def isEqual(int: Int): Boolean = {
_q.equals(int)
}
override def isEqual2(int: Int): Boolean = {
_p.equals(int)
}
}
17、Scala中的implicit
1、隐士转换函数
2、隐士转换变量
3、隐士转换类
package com
import scala.language.implicitConversions
object Demo19Implicit01 {
def main(args: Array[String]): Unit = {
/**
* 隐式转换:
* 在编写代码时 有些东西可以省略 让Scala的编译器自动去推断 能够减少代码的冗余
* 分类:
* 1、隐士转换函数
* 2、隐士转换变量
* 3、隐士转换类
*/
def printInt(int: Int): Unit = {
println(int)
}
printInt(100)
printInt(200)
// printInt("300") // 函数要求参数必须是Int类型
printInt(Integer.parseInt("300"))
// 有没有一种方式能够让String在需要转成Int时自动转为Int
// 隐式转换函数
implicit def str2Int(str: String): Int = {
Integer.parseInt(str)
}
printInt(str2Int("400"))
printInt("500")
}
}
package com
object Demo20Implicit02 {
def main(args: Array[String]): Unit = {
// 隐式转换变量
def addPrefix(head: String)(implicit prefix: String): Unit = {
println(head + "-" + prefix)
}
implicit val defaultPrefix: String = "默认的后缀"
addPrefix("Hadoop")("大象")
addPrefix("Hive")("蜂巢")
addPrefix("Spark")("火花")
addPrefix("HBase")
}
}
package com
import scala.io.Source
object Demo21Implicit03 {
def main(args: Array[String]): Unit = {
// 隐式转换类
val c1: FileReadAndPrint = new FileReadAndPrint("Scala/data/subject.txt")
c1.printFile()
val c2: FileReadAndPrint = new FileReadAndPrint("Scala/data/score.txt")
c2.printFile()
val c3: FileReadAndPrint = new FileReadAndPrint("Scala/data/students.txt")
c3.printFile()
"Scala/data/students.txt".printFile()
"Scala/data/score.txt".printFile()
}
implicit class FileReadAndPrint(path: String) {
var lines: List[String] = _
def readFile(): Unit = {
val bs = Source.fromFile(path)
lines = bs.getLines().toList
bs.close()
}
def printFile(): Unit = {
readFile()
lines.take(10).foreach(println)
}
}
}