scala函数。匿名函数、样例类
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) } } }