wqy1027

eeee

 

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)
    }
  }
}

 

posted on 2022-10-19 21:19  不想写代码的小玉  阅读(49)  评论(0编辑  收藏  举报

导航