Scala 的學習

JD_L發表於2023-05-10

Scala

只是學習無基本理論

安裝Scala

裝前必須有jdk

windows安裝

解壓縮 D:dev/scala

配置環境變數

SCALA_HONE

path

cmd檢查

Scala -version

直接輸入Scala 控制檯執行

idea安裝與執行Scala

idea-->外掛-->scala-->安裝-->重啟

新建maven專案

catalog-->maven

archetype-->

image

專案結構-->全域性庫-->新增Scala

image

image

新增應用支援-->scala
add開頭
image

image

新建Scala類 選擇 object

image

scala 完全物件導向

scala風格與java風格

public class JavaDemo01 {
    public static void main(String[] args) {
        System.out.println("我愛你中國");
    }
}
javac JavaDemo01
object ScalaDemo01{
    def main(args: Array[String]): Unit = {
    print("我愛你中國")
  }
}
scalac ScalaDemo01

終端執行Scala

編碼 utf-8

scalac 檔名字--> 生成 檔名字$.class 與 檔名字.class-->呼叫 檔名字.class

Scala專案啟動方式

main函式與extends app特質的區別:

App是scala語言內建的一個特質,使用它,則把對應object內部的整體作為scala main的一部分,有延遲啟動的特性。

同時,命令列引數args也作為App特質的一部分,可以被開發者直接使用。而main函式則是scala的預設啟動方式。

使用main函式

object ScalaDemo02{
    def main(args: Array[String]): Unit = {
    print("我愛你中國")
  }
}

使用App特質

object ScalaDemo03 extends App{
    print("我愛你中國")
}
object ScalaDemo04 extends App{
    print(args(0))
}

終端執行:

scalac ScalaDemo04.scala
scala ScalaDemo04 lhz

Scala程式碼與Java程式碼混用

object ScalaDemo05{
    def main(args: Array[String]): Unit = {
    System.out.println("我愛你中國")
  }
}

在 Scala 程式碼中 可以直接使用 Java 程式碼

注意:main 方法使用Scala 風格

變數與常量

object ScalaDemo06{
    def main(args: Array[String]): Unit = {
    // var 變數 修飾符
        var a:Int = 10
    // val 常量 修飾符
    	val b:Int = 10
        
        a = 20
        println(a)
        /**
         *報錯
         *reassignment to val
        */
        // b = 20
  }
}

字串基本使用

object ScalaDemo07{
    def main(args: Array[String]): Unit = {
        var str01:String = "我愛你"
        var str02:String = "中國"
        // java 風格
        println (str01 + str02)
        // 插值方式 與 python 風格比較相像
        var slogan:String = "桃李不言下自成蹊"
        println(s"slogan >>> $slogan")
        
        println("""
        	|我愛你中國
        	|親愛的母親
        """.strpMargin)
  }
}

選擇結構

object ScalaDemo08{
    def main(args: Array[String]): Unit = {
        var weekDay:Int = 1
        if (weekDay == 1){
            println("週一")
        }else if (weekDay == 2){
            println("週二")
        }else if (weekDay == 3){
            println("週三")
        }else if (weekDay == 4){
            println("週四")
        }else if (weekDay == 5){
            println("週五")
        }else if (weekDay == 6){
            println("週六")
        }else{
            println("週日")
  	}
  }
}

迴圈結構

object ScalaDemo09{
    def main(args: Array[String]): Unit = {
        var count:Int = 0
        while(count<5){
            println(count)
            count += 1
        }
  }
}
object ScalaDemo10{
    def main(args: Array[String]): Unit = {
        //Range 1 to 5
        println(1 to 5)
        println(1.to(5))
        println(1 until 5)
        println(1.until(5))
        
        // <- 賦值
        for (i <- 0 until 5){
            println(i)
        }
        println("--------------------^_ ~ _^----------------------")
        // 求偶數值
        for (i <- 0 until 10){
            if (i % 2 == 0){
                println(i)
            }
        }
        println("--------------^_ ~ _^----------------")
        for (i <- 0 until 10 if i % 2 == 0){
            println(i)
        }
        println("--------------^_ ~ _^----------------")
        for (i <- 0 until 10 by(2)){
            println(i)
        }
        println("--------------------^_ ~ _^----------------------")
        // 增強for迴圈
        var courses = Array("Hadoop","Hive","Sqoop","Flume","Hbase","Phoenix","Presto")
        for (course <- courses){
            println(course)
        }
  }
}

函式

無引數 無返回值

object ScalaDemo01{
    def main(args: Array[String]): Unit = {
    	sayHi()
  }
    // def 函式定義關鍵字 
    // sayHI 函式名稱
    // () 函式引數
    // :後面的資料型別為返回值資料型別
    // : Unit 無返回值的資料型別佔位符
    // {} 方法體
    private def sayHi(): Unit = {
      println("無引數 無返回值 函式 sayHi")  
    }
}

有引數 無返回值

object ScalaDemo02{
    def main(args: Array[String]): Unit = {
   	 sayHi(msg = "hello word")
  }
    private def sayHi(msg:String): Unit = {
        println("有引數 無返回值 函式 sayHi")
        println(s"引數是 >>> ${msg}")
    }
}

預設引數 無返回值

object ScalaDemo03{
    def main(args: Array[String]): Unit = {
    	sayHi()
        sayHi(msg = "hello")
  }
    private def sayHi(msg:String = "hi"): Unit = {
        println("預設引數 無返回值 函式 sayHi")
        println(s"引數是 >>> ${msg}")
    }
}
# 輸出結果:
預設引數 無返回值 函式 sayHi
引數是 >>> hi
預設引數 無返回值 函式 sayHi
引數是 >>> hello

有引數 有返回值

object ScalaDemo04{
    def main(args: Array[String]): Unit = {
    	println(sum(10,20))
  }
    def sum(a:Int , b:Int): Int ={
        // 函式的最後一行為返回值
        a+b
    }
}

可變引數 無返回值

public class JavaDemo04{
     public static void main(String[] args) {

    }
    private static String
}
object ScalaDemo05{
    def main(args: Array[String]): Unit = {
    	println(format())
        println(format(numbers = 1))
        println(format(numbers = 1,2))
  }
    def format(numbers: Int*): String = {
        // var result:String = null
        var result:Int = 0
    	if(numbers.size > 0){
            for(number <- numbers){
                result += number
            }
        }
        result
    }
}

物件導向

類與物件

object ScalaDemo01{
    def main(args: Array[String]): Unit = {
   		val person = new Person01
        person.name = "lhz"
        println(person.name)
  }
    class Person01{
        // _ 代表著 佔位符 佔位
        var name:String = _
    }
}

封裝

scala中屬性、方法預設為public

private只在類的內部和伴生物件中可用

protected,同類、子類可以訪問,同包無法訪問

private[包名],增加包訪問許可權,包名下的其他類也可以使用

Scala提供進一步的封裝,“public”屬性底層實際上都是private,訪問時本質上是呼叫了xxx(get) 和 xxx_eq$(set) 方法,

但這裡的方法名並不是getXXX和setXXX,由於一些Java框架會利用反射呼叫getXXX和setXXX,

因此Scala也提供了上面提到過的@BeanProperty註解去生成某屬性的這兩個方法,

但注意@BeanProperty不能加在private修飾的屬性上,

可以理解為由於“public”本身就是private,將變數修飾為private然後再提供getter、setter方法比較冗餘,Scala不推薦這樣做。

// 假 封裝
object ScalaDemo02{
    def main(args: Array[String]): Unit = {
   		val person = new Person02
        person.setName("lhz")
        println(person.getName)
        person.name = "lz"
        println(person.name)
  }
    class Person02{
        // _ 代表著 佔位符 佔位
        @BeanProperty
        var name:String = _
    }
}
// private 不推薦
// 手寫 set get 方法
object ScalaDemo03 {
  def main(args: Array[String]): Unit = {
   val person = new Person03
   person.setName("lhz")
   println(person.getName)
  }
  class Person03{
    private var name: String = _

    def getName: String = {
      this.name
    }

    def setName(name: String): Unit ={
      this.name = name
    }
  }
}

java程式碼混用

public class Person04 {
    private String realName;

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }
}
object ScalaDemo04 {
  def main(args: Array[String]): Unit = {
    val person = new Person04
    person.setRealName("李昊哲")
    println(person.getRealName)
  }
}

建構函式

object ScalaDemo05{
    def main(args: Array[String]): Unit = {
   		val person01 = new Person05("person01","220422198311222011")
    val person02 = new Person05("person02","220422198311222011",15311484567L)
    val person03 = new Person05("person02","220422198311222011","我愛你中國")
    val person04 = new Person05("person02","220422198311222011",15311484568L,"我愛你中國")
    println(person01)
    println(person02)
    println(person03)
    println(person04)
  }
}
    //主建構函式
class Person05(val realName:String, val idCard:String){
	println("Person05 主構造器 執行了")
    var mobile: Long= _
    var slogan: String= _
        
    // 輔助構函式 輔助構函式不能有型別註解
    def this(realName: String , idCard: String, mobile: Long)={
            // 輔助構函式 的 第一行程式碼必須呼叫 主建構函式 或者其他 輔助構函式
            this(realName,idCard)
            this.mobile = mobile
        }
        def this(realName: String , idCard: String, Slogan: String)={
            // 輔助構函式 的 第一行程式碼必須呼叫 主建構函式 或者其他 輔助構函式
            this(realName,idCard)
            this.slogan = slogan
        }
        def this(realName: String , idCard: String, mobile: Long, slogan: String)={
            // 輔助構函式 的 第一行程式碼必須呼叫 主建構函式 或者其他 輔助構函式
            this(realName,idCard,mobile)
            this.slogan = slogan
        }
    override def toString: String =
    this.getClass.getSimpleName +
      ", realName:" + realName +
      ", idCard:"+ idCard +
      ", mobile:" + mobile +
      ", slogan:"  + slogan

}

執行結果

Person05 主構造器 執行了
Person05 主構造器 執行了
Person05 主構造器 執行了
Person05 主構造器 執行了
Person05, realName:person01, idCard:220422198311222011, mobile:0, slogan:null
Person05, realName:person02, idCard:220422198311222011, mobile:15311484567, slogan:null
Person05, realName:person02, idCard:220422198311222011, mobile:0, slogan:我愛你中國
Person05, realName:person02, idCard:220422198311222011, mobile:15311484568, slogan:我愛你中國

繼承

object ScalaDemo06 {
  def main(args: Array[String]): Unit = {
    val worker = new Worker("李昊哲", "15311484568", "架構師")
    println(worker)
  }
}

// 主建構函式
class Person06(val realName: String, val mobile: String) {

  println("Person06 主構造器 執行了")

  override def toString: String =
    this.getClass.getSimpleName +
      ", realName:" + realName +
      ", mobile:" + mobile
}

class Worker(realName: String, mobile: String, job: String) extends Person06(realName, mobile) {
  println("Worker 主構造器 執行了")

  override def toString: String =
    this.getClass.getSimpleName +
      ", realName:" + realName +
      ", mobile:" + mobile +
      ", job:" + job
}

抽象類

object ScalaDemo07 {
  def main(args: Array[String]): Unit = {
    val teacher = new Teacher
    teacher.realName = "李昊哲"
    teacher.mobile = "15311484568"
    println(teacher)
    teacher.hi()
  }
}

abstract class Person07() {

  println("Person07 主構造器 執行了")

  var realName: String
  var mobile: String

  def hi(): Unit

  override def toString: String =
    this.getClass.getSimpleName +
      ", realName:" + realName +
      ", mobile:" + mobile
}

class Teacher extends Person07 {
  println("Teacher 主構造器 執行了")

  override def toString: String =
    this.getClass.getSimpleName +
      ", realName:" + realName +
      ", mobile:" + mobile

  override var realName: String = _
  override var mobile: String = _

  override def hi(): Unit = {
    println("接著奏樂 接著舞")
  }
}

伴生類與伴生物件

scala中的類不能定義靜態成員,而代之以定義單例物件來替代
單例物件透過object關鍵字來宣告
單例物件中的所有方法,可以直接透過object單例物件的名字直接來呼叫。
一個單例物件可以繫結在一個類,當單例物件和某個類寫在同一個原始檔且共享一個名字,它們就產生了繫結關係。
此時單例物件稱之為該類的伴生物件,類稱之為該物件的伴生類。

類和它的伴生物件可以互相訪問其私有成員
單例物件不能new,所以也沒有構造引數
可以把單例物件當做java中可能會用到的靜態方法工具類。
作為程式入口的方法必須是靜態的,所以main方法必須處在一個單例物件中,而不能寫在一個類中。

object ScalaDemo08 {
  def main(args: Array[String]): Unit = {
    Food.printMsg()
    new Food().printSlogan()
  }
}

class Food {
  private val msg: String = "hello"
  def printSlogan(): Unit = {
    println(Food.slogan)
  }
}

object Food {
  private val slogan: String = "桃李不言下自成蹊"
  def printMsg(): Unit = {
    println(new Food().msg)
  }
}

apply

object ScalaDemo09 {
  def main(args: Array[String]): Unit = {
    // Drink() 相當於 Drink.apply
    Drink()
    new Drink().apply()
  }
}

class Drink{
  def apply(): Unit = {
    println("class Food 執行...")
  }
}

object Drink {
  def apply(): Unit = {
    println("object Food 執行...")
  }
}

資料結構

Array陣列

Java

public class JavaDemo01 {
    public static void main(String[] args) {
        String[] courses = new String[5];
        courses[0] = "hadoop";
        System.out.println(courses[0]);
        String[] hobbies = {"swim", "walk", "photography"};
        for (String hobby : hobbies) {
            System.out.println(hobby);
        }
    }
}

scala

object ScalaDemo01 {
  def main(args: Array[String]): Unit = {
    val courses = new Array[String](5)
    println(courses.length)
    courses(0) = "hadoop";
    println(courses(0))
    val hobbies = Array("swim", "walk", "photography")
    for (hobby <- hobbies) {
      println(hobby)
    }
  }
}

Array常用方法

object ScalaDemo02 {
  def main(args: Array[String]): Unit = {
    val numbers = Array(2,4,6,8,0,1,3,5,7,9)
    // 求和
    val sumResult = numbers.sum
    println("sumResult = " + sumResult)

    // 最大值
    val maxResult = numbers.max
    println("maxResult = " + maxResult)

    // 最小值
    val minResult = numbers.min
    println("minResult = " + minResult)

    // 排序
    val sortedNumbers = numbers.sorted
    for (number <- sortedNumbers){
      println(number)
    }
    println("++++++++++++++++++++")
    val reverseNumbers = sortedNumbers.reverse
    for (number <- reverseNumbers) {
      println(number)
    }
  }
}

可變長Array

object ScalaDemo03 {
  def main(args: Array[String]): Unit = {
    val courses = ArrayBuffer[String]()
    courses += "hadoop"
    courses += "hive"
    courses += "Chinese"
    courses += "math"
    courses ++= Array("presto","hbase","phoenix","scala","spark")
    // 在下標 1 的位置插入
    courses.insert(1,"logger")
    // 移除 下標 5 的內容
    courses.remove(5)
    // 移除 下標 2-4 的內容
    courses.remove(2,4)
    for (course <- courses){
      println(course)
    }
  }
}

List 集合

Scala 列表類似於陣列,它們所有元素的型別都相同,

但是它們也有所不同:列表是不可變的,值一旦被定義了就不能改變,

其次列表 具有遞迴的結構(也就是連結表結構)而陣列不是。

object ScalaDemo04 {
  def main(args: Array[String]): Unit = {
    val courses = List("presto","hbase","phoenix","scala","spark")
    for (course <- courses) {
      println(course)
    }
  }
}
object ScalaDemo05 {
  def main(args: Array[String]): Unit = {
    val courses = ListBuffer[String]()
    courses += "hadoop"
    courses += "hive"
    courses ++= List("presto", "hbase", "phoenix", "scala", "spark")
    for (course <- courses) {
      println(course)
    }
  }
}
object ScalaDemo06 {
  def main(args: Array[String]): Unit = {
    val courses = ListBuffer[String]()
    courses += "hadoop"
    courses += "hive"
    courses ++= List("presto", "hbase", "phoenix", "scala", "spark")
    println(courses.head)
    println(courses.tail)
  }
}

Nil

object ScalaDemo07 {
  def main(args: Array[String]): Unit = {
    println(Nil)
    val courses = "hadoop" :: "presto" :: "hbase" :: Nil
    println("courses 元素數量 >>> " + courses.size)
    for (course <- courses) {
      println(course)
    }
  }
}

Set

Scala Set(集合)是沒有重複的物件集合,所有的元素都是唯一的。

Scala 集合分為可變的和不可變的集合。

預設情況下,Scala 使用的是不可變集合,如果你想使用可變集合,需要引用 scala.collection.mutable.Set 包。

object ScalaDemo08 {
  def main(args: Array[String]): Unit = {
    val courses = Set("presto","hbase","phoenix","scala","spark","hbase","scala")
    for (course <- courses) {
      println(course)
    }
  }
}
object ScalaDemo09 {
  def main(args: Array[String]): Unit = {
    val courses = mutable.HashSet[String]()
    courses += "hadoop"
    courses += "hive"
    courses ++= List("presto", "hbase", "phoenix", "scala", "spark")
    for (course <- courses) {
      println(course)
    }
  }
}


Map

object ScalaDemo10 {
  def main(args: Array[String]): Unit = {
    val a = Map("k1" -> "v1", "k2" -> "v2", "k3" -> "v3")
    println(a("k1"))
    // java.util.NoSuchElementException: key not found: k5
    // println(a("k5"))
    println(a.getOrElse("k1",null))
    println(a.getOrElse("k5",null))
  }
}
object ScalaDemo11 {
  def main(args: Array[String]): Unit = {
    val map = mutable.HashMap[String, String]()
    map += ("k1" -> "v1")
    println(map.getOrElse("k1", null))
  }
}
object ScalaDemo12 {
  def main(args: Array[String]): Unit = {
    val map = mutable.HashMap[String, String]()
    map += ("k1" -> "v1")
    map += ("k2" -> "v2")
    map += ("k3" -> "v3")
    map += ("k4" -> "v4")
    map += ("k5" -> "v5")
    for ((key, value) <- map) {
      println(key + " >>> " + value)
    }
  }
}
object ScalaDemo13 {
  def main(args: Array[String]): Unit = {
    val map = mutable.HashMap[String, String]()
    map += ("k1" -> "v1")
    map += ("k2" -> "v2")
    map += ("k3" -> "v3")
    map += ("k4" -> "v4")
    map += ("k5" -> "v5")
    val keySet = map.keySet
    for (key <- keySet) {
      println(key + " >>> " + map.getOrElse(key, null))
    }
  }
}
object ScalaDemo13 {
  def main(args: Array[String]): Unit = {
    val map = mutable.HashMap[String, String]()
    map += ("k1" -> "v1")
    map += ("k2" -> "v2")
    map += ("k3" -> "v3")
    map += ("k4" -> "v4")
    map += ("k5" -> "v5")
    val values = map.values
    for (value <- values) {
      println(value)
    }
  }
}
object ScalaDemo14 {
  def main(args: Array[String]): Unit = {
    val map = mutable.HashMap[String, String]()
    map += ("k1" -> "v1")
    map += ("k2" -> "v2")
    map += ("k3" -> "v3")
    map += ("k4" -> "v4")
    map += ("k5" -> "v5")
    for ((key, _) <- map) {
      println(key + " >>> " + map.getOrElse(key, null))
    }
  }
}

Tuple

與列表一樣,元組也是不可變的,但與列表不同的是元組可以包含不同型別的元素。

元組的值是透過將單個的值包含在圓括號中構成的

object ScalaDemo15 {
  def main(args: Array[String]): Unit = {
    val t1 = (1, 3.14, "李昊哲")
    for (i <- 0 until (t1.productArity)) {
      println(t1.productElement(i))
    }
    val protocol: String = "http"
    val domain: String = "localhost"
    val port: Int = 80
    val context: String = "lhz"
    val url = (protocol, domain, port, context)
    println(url._1)
    println(url._2)
    println(url._3)
    println(url._4)
  }
}

異常機制

object ScalaDemo01 {
  def main(args: Array[String]): Unit = {
    try {
      println(1 / 1)
      println(1 / 0)
    } catch {
      case e: ArithmeticException => println("數學異常")
    } finally {
      println("釋放資源")
    }
  }
}

匹配模式

java switch

從java14開始, switch語句有了一個很大的調整, 這就讓swicth語句有了更多的操作和選擇,在程式碼上,更加的簡便靈活.

  • switch 標準方式
  • switch - > 用法:
  • switch yield 用法:
標準方式
public class JavaDemo01 {
    public static void main(String[] args) {
        int dayOfWeek = 2;
        switch (dayOfWeek) {
            case 1:
                System.out.println("星期一");
            case 2:
                System.out.println("星期二");
            case 3:
                System.out.println("星期三");
            case 4:
                System.out.println("星期四");
            case 5:
                System.out.println("星期五");
            case 6:
                System.out.println("星期六");
            default:
                System.out.println("星期日");
        }
    }
}

從輸出結果發現case程式碼塊被穿透了,使用break防止case程式碼執行穿透,程式碼如下:

public class JavaDemo02 {
    public static void main(String[] args) {
        int dayOfWeek = 2;
        switch (dayOfWeek) {
            case 1:
                System.out.println("星期一");
                break;
            case 2:
                System.out.println("星期二");
                break;
            case 3:
                System.out.println("星期三");
                break;
            case 4:
                System.out.println("星期四");
                break;
            case 5:
                System.out.println("星期五");
                break;
            case 6:
                System.out.println("星期六");
                break;
            default:
                System.out.println("星期日");
                break;
        }
    }
}
switch - > 用法:

使用switch標準方式編寫程式碼太多的break造成程式碼冗餘可讀性不高 可以藉助函式式介面和lambda表示式簡化書寫

int dayOfWeek = 2;
switch (dayOfWeek) {
    case 1 -> System.out.println("星期一");
    case 2 -> System.out.println("星期二");
    case 3 -> System.out.println("星期三");
    case 4 -> System.out.println("星期四");
    case 5 -> System.out.println("星期五");
    case 6 -> System.out.println("星期六");
    default -> System.out.println("星期日");
}
switch yield 用法:返回值

先來開一段標準模式的程式碼:

public class JavaDemo04 {
    public static void main(String[] args) {
        String weekday = null;
        int dayOfWeek = 2;
        switch (dayOfWeek) {
            case 1:
                weekday = "星期一";
                break;
            case 2:
                weekday = "星期二";
                break;
            case 3:
                weekday = "星期三";
                break;
            case 4:
                weekday = "星期四";
                break;
            case 5:
                weekday = "星期五";
                break;
            case 6:
                weekday = "星期六";
                break;
            default:
                weekday = "星期日";
                break;
        }
        System.out.println(weekday);
    }
}

從上面程式碼不難看出我們透過條件匹配為變數賦值,再來看看switch yield的簡化寫法

public class JavaDemo05 {
    public static void main(String[] args) {
        int dayOfWeek = 2;
        String weekday = switch (dayOfWeek) {
            case 1:
                yield "星期一";
            case 2:
                yield "星期二";
            case 3:
                yield "星期三";
            case 4:
                yield "星期四";
            case 5:
                yield "星期五";
            case 6:
                yield "星期六";
            default:
                yield "星期日";
        };
        System.out.println(weekday);
    }
}

scala math

object ScalaDemo01 {
  def main(args: Array[String]): Unit = {
    val dayOfWeek: Int = 2
    dayOfWeek match {
      case 1 => System.out.println("星期一")
      case 2 => System.out.println("星期二")
      case 3 => System.out.println("星期三")
      case 4 => System.out.println("星期四")
      case 5 => System.out.println("星期五")
      case 6 => System.out.println("星期六")
      case _ => System.out.println("星期日")
    }
  }
}

偏函式

被包在花括號內沒有match的一組case語句

輸入引數的資料型別

輸出引數的資料型別

/**
 * 偏函式
 * 被包在花括號內沒有match的一組case語句
 */
object ScalaDemo02 {
  def main(args: Array[String]): Unit = {
    val weekDay = chime(2)
    println(weekDay)
  }

  /**
   * A 輸入引數的資料型別
   * B 輸出引數的資料型別
   * @return
   */
  def chime:PartialFunction[Int,String] = {
    case 1 => "星期一"
    case 2 => "星期二"
    case 3 => "星期三"
    case 4 => "星期四"
    case 5 => "星期五"
    case 6 => "星期六"
    case _ => "星期日"
  }
}

顆粒化函式

object ScalaDemo01 {
  def main(args: Array[String]): Unit = {
    def sum01(x: Int, y: Int) = x + y

    println(sum01(10, 20))

    def sum02(x: Int)(y: Int) = x + y

    println(sum02(10)(20))

  }
}

匿名函式

定義個沒有名稱的函式我們稱之為匿名函式

箭頭左邊是引數列表,右邊是函式體。

object ScalaDemo02 {
  def main(args: Array[String]): Unit = {
   val result = (x:Int) => x * 2
    println(result(10))
  }
}

高階函式

foreach

遍歷

public class JavaDemo03 {
    public static void main(String[] args) {
        List<Integer> nums = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
        nums.forEach(System.out::println);
    }
}
object ScalaDemo03 {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    nums.foreach(num => println(num))
  }
}

map

逐個操作列表中每一個元素

public class JavaDemo04 {
    public static void main(String[] args) {
        List<Integer> nums = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
        List<Integer> numbers = nums.stream().map(num -> num * 2).toList();
        numbers.forEach(System.out::println);
    }
}
object ScalaDemo04 {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    val numbers = nums.map(num => num * 2)
    numbers.foreach(num => println(num))
  }
}
object ScalaDemo05 {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    val numbers = nums.map(_ * 2)
    numbers.foreach(num => println(num))
  }
}

flatten flatMap

flatMap

flatten

先對集合中每個元素進行map,再對map後的每個元素進行flatten

map後的每個元素也是一個集合

public class JavaDemo06 {
    public static void main(String[] args) {
        List<Integer> listA = new ArrayList<>();
        listA.add(1);
        listA.add(2);

        List<Integer> listB = new ArrayList<>();
        listA.add(5);
        listA.add(6);

        List<List<Integer>> listC = new ArrayList<>();
        listC.add(listA);
        listC.add(listB);

        List<Integer> numbers = listC.stream().flatMap(Collection::stream).toList();
        numbers.forEach(System.out::println);
    }
}
object ScalaDemo06 {
  def main(args: Array[String]): Unit = {
    val nums = List(List(1, 2), List(5, 6))
    val numbers = nums.flatten
    numbers.foreach(num => println(num))
  }
}

filter

過濾出符合規則的資料生成新的列表

public class JavaDemo07 {
    public static void main(String[] args) {
        List<Person> persons = new ArrayList<>();
        Person person;
        for (int i = 0; i < 10; i++) {
            person = new Person("user" + (i + 1), (i + 1) % 2);
            persons.add(person);
        }
        // 獲取男性列表
        List<Person> manList = persons.stream().filter(user -> user.getGender() == 1).toList();

        // 獲取女性列表
        List<Person> womanList = persons.stream().filter(user -> user.getGender() == 0).toList();

        manList.forEach(System.out::println);
        System.out.println("+++++++++++++++++++++++");
        womanList.forEach(System.out::println);
    }
}

class Person {
    private String name;
    private int gender;

    public Person() {
    }

    public Person(String name, int gender) {
        this.name = name;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getGender() {
        return gender;
    }

    public void setGender(int gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", gender=" + gender +
                '}';
    }
}

執行結果:

Person{name='user1', gender=1}
Person{name='user3', gender=1}
Person{name='user5', gender=1}
Person{name='user7', gender=1}
Person{name='user9', gender=1}
+++++++++++++++++++++++
Person{name='user2', gender=0}
Person{name='user4', gender=0}
Person{name='user6', gender=0}
Person{name='user8', gender=0}
Person{name='user10', gender=0}
object ScalaDemo07 {
  def main(args: Array[String]): Unit = {
    val users = new ListBuffer[User]()
    var user: User = null
    for (i <- 0 until 10) {
      user = new User("user" + (i + 1),(i + 1) % 2)
      users += user
    }
    // 獲取男性列表
    val manList = users.filter(ele => ele.getGender % 2 == 1)
    // 獲取女性列表
    val womanList = users.filter(ele => ele.getGender % 2 == 0)

    manList.foreach(man => println(man))
    println("+++++++++++++++++++++++")
    womanList.foreach(woman => println(woman))
  }
}

class User {
  @BeanProperty
  var name: String = _
  @BeanProperty
  var gender: Int = _

  def this(name:String,gender:Int) = {
    this()
    this.name = name
    this.gender = gender
  }

  override def toString: String = "User{" + "name='" + name + '\'' + ", gender=" + gender + '}'
}
object ScalaDemo07 {
  def main(args: Array[String]): Unit = {
    val users = new ListBuffer[User]()
    var user: User = null
    for (i <- 0 until 10) {
      user = new User("user" + (i + 1),(i + 1) % 2)
      users += user
    }
    // 獲取男性列表
    val manList = users.filter(ele => ele.getGender % 2 == 1)
    // 獲取女性列表
    val womanList = users.filter(ele => ele.getGender % 2 == 0)

    manList.foreach(man => println(man))
    println("+++++++++++++++++++++++")
    womanList.foreach(woman => println(woman))
  }
}

class User {
  @BeanProperty
  var name: String = _
  @BeanProperty
  var gender: Int = _

  def this(name:String,gender:Int) = {
    this()
    this.name = name
    this.gender = gender
  }

  override def toString: String = "User{" + "name='" + name + '\'' + ", gender=" + gender + '}'
}

執行結果:

User{name='user1', gender=1}
User{name='user3', gender=1}
User{name='user5', gender=1}
User{name='user7', gender=1}
User{name='user9', gender=1}
+++++++++++++++++++++++
User{name='user2', gender=0}
User{name='user4', gender=0}
User{name='user6', gender=0}
User{name='user8', gender=0}
User{name='user10', gender=0}

reduce

相鄰兩個元素轉為一個元素

列表中的所有元素轉為一個元素

1, 2, 3, 4, 5, 6, 7, 8, 9
-1, 3, 4, 5, 6, 7, 8, 9
-4, 4, 5, 6, 7, 8, 9
-8, 5, 6, 7, 8, 9
-13, 6, 7, 8, 9
-19, 7, 8, 9
-26, 8, 9
-34, 9
-43
public class JavaDemo08 {
    public static void main(String[] args) {
        List<Integer> nums = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
        List<Integer> numbers = nums.stream().reduce((a, b) -> a - b).stream().toList();
        numbers.forEach(System.out::println);
    }
}
object ScalaDemo08 {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    // val num = nums.reduce((a, b) => a - b)
    val num = nums.reduceLeft(_ - _)
    println(num)
  }
}

reduceLeft

object ScalaDemo09 {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    // val num = nums.reduceLeft((a, b) => a - b)
    val num = nums.reduceLeft(_ - _)
    println(num)
  }
}

reduceRight

1, 2, 3, 4, 5, 6, 7, 8, 9
1, 2, 3, 4, 5, 6, 7, 1
1, 2, 3, 4, 5, 6, -6
1, 2, 3, 4, 5, -12
1, 2, 3, 4, -17
1, 2, 3, -21
1, 2, -24
1, -26
-27
object ScalaDemo10 {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    val num = nums.reduceRight((a, b) => b - a)
    println(num)
  }
}

// -27
1, 2, 3, 4, 5, 6, 7, 8, 9
1, 2, 3, 4, 5, 6, 7, -1
1, 2, 3, 4, 5, 6, 8
1, 2, 3, 4, 5, -2
1, 2, 3, 4, 7
1, 2, 3, -3
1, 2, 6
1, -4
5
object ScalaDemo10 {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    val num = nums.reduceRight((a, b) => _ - _)
    println(num)
  }
}

//-27

count

計數器

public class JavaDemo12 {
    public static void main(String[] args) {
        List<Integer> nums = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
        long count = nums.stream().filter(num -> num % 2 == 0).count();
        System.out.println("列表中偶數是數量 >>> " + count);
    }
}
object ScalaDemo12 {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    val count = nums.count(num => num % 2 == 0)
    println(count)
  }
}

//4

distinct

public class JavaDemo13 {
    public static void main(String[] args) {
        List<Integer> nums = List.of(1, 2, 3, 5, 6, 7, 8, 9, 3, 4, 5, 7, 8, 2, 3);
        List<Integer> numbers = nums.stream().distinct().toList();
        numbers.forEach(System.out::println);
    }
}
object ScalaDemo13 {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 5, 6, 7, 8, 9, 3, 4, 5, 7, 8, 2, 3);
    val numbers = nums.distinct
    numbers.foreach(num => println(num))
  }
}

sorted

排序類需要實現 Comparable 介面

public class JavaDemo14 {
    public static void main(String[] args) {
        List<Dog> dogs = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            dogs.add(new Dog("dog" + (i + 1), ThreadLocalRandom.current().nextInt(1, 10)));
        }
        dogs.forEach(System.out::println);
        List<Dog> newDogs = dogs.stream().sorted((a, b) -> a.getAge() - b.getAge()).toList();
        System.out.println("++++++++++++++");
        newDogs.forEach(System.out::println);
    }
}

class Dog {
    private String name;
    private int age;

    public Dog() {
    }

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

執行結果:

Dog{name='dog1', age=3}
Dog{name='dog2', age=3}
Dog{name='dog3', age=3}
Dog{name='dog4', age=3}
Dog{name='dog5', age=7}
Dog{name='dog6', age=6}
Dog{name='dog7', age=4}
Dog{name='dog8', age=8}
Dog{name='dog9', age=7}
Dog{name='dog10', age=2}
++++++++++++++
Dog{name='dog10', age=2}
Dog{name='dog1', age=3}
Dog{name='dog2', age=3}
Dog{name='dog3', age=3}
Dog{name='dog4', age=3}
Dog{name='dog7', age=4}
Dog{name='dog6', age=6}
Dog{name='dog5', age=7}
Dog{name='dog9', age=7}
Dog{name='dog8', age=8}
object ScalaDemo14 {
  def main(args: Array[String]): Unit = {
    val random = new Random()
    val cats = List(
      new Cat("cat1", random.between(1, 10)),
      new Cat("cat2", random.between(1, 10)),
      new Cat("cat3", random.between(1, 10)),
      new Cat("cat4", random.between(1, 10)),
      new Cat("cat5", random.between(1, 10)),
      new Cat("cat6", random.between(1, 10)),
      new Cat("cat7", random.between(1, 10)),
      new Cat("cat8", random.between(1, 10)),
      new Cat("cat9", random.between(1, 10)),
      new Cat("cat10", random.between(1, 10)),
    )
    cats.foreach(cat => println(cat))
    println("++++++++++++++++++++++")
    val newCats = cats.sorted
    newCats.foreach(cat => println(cat))
  }
}

class Cat extends Comparable[Cat] {
  @BeanProperty
  var name: String = _
  @BeanProperty
  var age: Int = _

  def this(name: String, age: Int) = {
    this()
    this.name = name
    this.age = age
  }

  override def compareTo(o: Cat): Int = this.getAge - o.getAge

  override def toString = s"Cat(name=$name, age=$age)"
}

執行結果:

Cat(name=cat1, age=8)
Cat(name=cat2, age=4)
Cat(name=cat3, age=5)
Cat(name=cat4, age=1)
Cat(name=cat5, age=5)
Cat(name=cat6, age=5)
Cat(name=cat7, age=2)
Cat(name=cat8, age=3)
Cat(name=cat9, age=8)
Cat(name=cat10, age=5)
++++++++++++++++++++++
Cat(name=cat4, age=1)
Cat(name=cat7, age=2)
Cat(name=cat8, age=3)
Cat(name=cat2, age=4)
Cat(name=cat3, age=5)
Cat(name=cat5, age=5)
Cat(name=cat6, age=5)
Cat(name=cat10, age=5)
Cat(name=cat1, age=8)
Cat(name=cat9, age=8)

sortBy

不需要寫程式碼邏輯 只需要制定排序指標即可

object ScalaDemo15 {
  def main(args: Array[String]): Unit = {
    val random = new Random()
    val pigs = List(
      new Pig("pig1", random.between(1, 10)),
      new Pig("pig2", random.between(1, 10)),
      new Pig("pig3", random.between(1, 10)),
      new Pig("pig4", random.between(1, 10)),
      new Pig("pig5", random.between(1, 10)),
      new Pig("pig6", random.between(1, 10)),
      new Pig("pig7", random.between(1, 10)),
      new Pig("pig8", random.between(1, 10)),
      new Pig("pig9", random.between(1, 10)),
      new Pig("pig10", random.between(1, 10)),
    )
    pigs.foreach(pig => println(pig))
    println("++++++++++++++++++++++")
    // 不需要寫程式碼邏輯 只需要制定排序指標即可
    val newPigs = pigs.sortBy(pig => pig.getAge)
    newPigs.foreach(pig => println(pig))
  }
}

class Pig {
  @BeanProperty
  var name: String = _
  @BeanProperty
  var age: Int = _

  def this(name: String, age: Int) = {
    this()
    this.name = name
    this.age = age
  }

  override def toString = s"Pig(name=$name, age=$age)"
}

執行結果:

Pig(name=pig2, age=8)
Pig(name=pig3, age=8)
Pig(name=pig4, age=3)
Pig(name=pig5, age=8)
Pig(name=pig6, age=1)
Pig(name=pig7, age=7)
Pig(name=pig8, age=8)
Pig(name=pig9, age=3)
Pig(name=pig10, age=1)
++++++++++++++++++++++
Pig(name=pig6, age=1)
Pig(name=pig10, age=1)
Pig(name=pig1, age=2)
Pig(name=pig4, age=3)
Pig(name=pig9, age=3)
Pig(name=pig7, age=7)
Pig(name=pig2, age=8)
Pig(name=pig3, age=8)
Pig(name=pig5, age=8)
Pig(name=pig8, age=8)

sortWtih

傳遞一個函式 然後在函式內編寫排序規則

object ScalaDemo16  {
  def main(args: Array[String]): Unit = {
    val random = new Random()
    val birds = List(
      new Bird("bird1", random.between(1, 10)),
      new Bird("bird2", random.between(1, 10)),
      new Bird("bird3", random.between(1, 10)),
      new Bird("bird4", random.between(1, 10)),
      new Bird("bird5", random.between(1, 10)),
      new Bird("bird6", random.between(1, 10)),
      new Bird("bird7", random.between(1, 10)),
      new Bird("bird8", random.between(1, 10)),
      new Bird("bird9", random.between(1, 10)),
      new Bird("bird10", random.between(1, 10)),
    )
    birds.foreach(Bird => println(Bird))
    println("++++++++++++++++++++++")
    // 傳遞一個函式 然後在函式內編寫排序規則
    val newBirds = birds.sortWith((a, b) => a.getAge - b.getAge <= 0).toList
    newBirds.foreach(bird => println(bird))
  }
}

class Bird {
  @BeanProperty
  var name: String = _
  @BeanProperty
  var age: Int = _

  def this(name: String, age: Int) = {
    this()
    this.name = name
    this.age = age
  }

  override def toString = s"Bird(name=$name, age=$age)"
}

執行結果:

Bird(name=bird1, age=7)
Bird(name=bird2, age=1)
Bird(name=bird3, age=9)
Bird(name=bird4, age=2)
Bird(name=bird5, age=5)
Bird(name=bird6, age=2)
Bird(name=bird7, age=4)
Bird(name=bird8, age=1)
Bird(name=bird9, age=9)
Bird(name=bird10, age=9)
++++++++++++++++++++++++++
Bird(name=bird8, age=1)
Bird(name=bird2, age=1)
Bird(name=bird6, age=2)
Bird(name=bird4, age=2)
Bird(name=bird7, age=4)
Bird(name=bird5, age=5)
Bird(name=bird1, age=7)
Bird(name=bird10, age=9)
Bird(name=bird9, age=9)
Bird(name=bird3, age=9)

take

TopN

public class JavaDemo17 {
    public static void main(String[] args) {
        int base = 1000;
        ArrayList<Video> videos = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            videos.add(new Video(base + i + 1, ThreadLocalRandom.current().nextInt(100, 1000)));
        }
        videos.forEach(System.out::println);
        System.out.println("+++++++++++++");
        videos.sort((a, b) -> b.getGold() - a.getGold());
        List<Video> topList = videos.stream().limit(3).toList();
        topList.forEach(System.out::println);
    }
}

執行結果:

Video{vid='1001', gold=566}
Video{vid='1002', gold=548}
Video{vid='1003', gold=620}
Video{vid='1004', gold=897}
Video{vid='1005', gold=264}
Video{vid='1006', gold=311}
Video{vid='1007', gold=882}
Video{vid='1008', gold=870}
Video{vid='1009', gold=106}
Video{vid='1010', gold=185}
+++++++++++++
Video{vid='1004', gold=897}
Video{vid='1007', gold=882}
Video{vid='1008', gold=870}
object ScalaDemo17 {
  def main(args: Array[String]): Unit = {
    val random = new Random()
    val videos = List(
      new VideoInfo(1001, random.between(100, 1000)),
      new VideoInfo(1001, random.between(100, 1000)),
      new VideoInfo(1001, random.between(100, 1000)),
      new VideoInfo(1001, random.between(100, 1000)),
      new VideoInfo(1001, random.between(100, 1000)),
      new VideoInfo(1001, random.between(100, 1000)),
      new VideoInfo(1001, random.between(100, 1000)),
      new VideoInfo(1001, random.between(100, 1000)),
      new VideoInfo(1001, random.between(100, 1000)),
      new VideoInfo(1001, random.between(100, 1000))
    )
    videos.foreach(video => println(video))
    println("++++++++++++++++++++++++++++")
    val videoSortList = videos.sortWith((a, b) => a.getGold - b.getGold >= 0).toList
    val videoTopList = videoSortList.take(3).toList
    videoTopList.foreach(video => println(video))
  }

}

class VideoInfo {
  @BeanProperty
  var name: Int = _
  @BeanProperty
  var gold: Int = _

  def this(name: Int, gold: Int) = {
    this()
    this.name = name
    this.gold = gold
  }

  override def toString = s"VideoInfo(name=$name, gold=$gold)"
}
VideoInfo(name=1001, gold=660)
VideoInfo(name=1002, gold=870)
VideoInfo(name=1003, gold=405)
VideoInfo(name=1004, gold=356)
VideoInfo(name=1005, gold=165)
VideoInfo(name=1006, gold=452)
VideoInfo(name=1007, gold=698)
VideoInfo(name=1008, gold=138)
VideoInfo(name=1009, gold=839)
VideoInfo(name=1010, gold=211)
++++++++++++++++++++++++++++
VideoInfo(name=1002, gold=870)
VideoInfo(name=1009, gold=839)
VideoInfo(name=1007, gold=698)

groupBy

分組

public class JavaDemo18 {
    public static void main(String[] args) {
        List<Animal> animals = new ArrayList<>();
        Animal animal;
        for (int i = 0; i < 10; i++) {
            animal = new Animal("animal" + (i + 1), (i + 1) % 2);
            animals.add(animal);
        }
        // 按照性別分組
        Map<Integer, List<Animal>> animalGenderGroup = animals.stream().collect(Collectors.groupingBy(Animal::getGender));
        animalGenderGroup.forEach((key, value) -> System.out.println((key == 1 ? "雄性" : "雌性") + " >>> " + value));
    }
}

class Animal {
    private String name;
    private int gender;

    public Animal() {
    }

    public Animal(String name, int gender) {
        this.name = name;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getGender() {
        return gender;
    }

    public void setGender(int gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                ", gender=" + gender +
                '}';
    }
}

執行結果:

雌性 >>> [Animal{name='animal2', gender=0}, Animal{name='animal4', gender=0}, Animal{name='animal6', gender=0}, Animal{name='animal8', gender=0}, Animal{name='animal10', gender=0}]
雄性 >>> [Animal{name='animal1', gender=1}, Animal{name='animal3', gender=1}, Animal{name='animal5', gender=1}, Animal{name='animal7', gender=1}, Animal{name='animal9', gender=1}]
object ScalaDemo18 {
  def main(args: Array[String]): Unit = {
    val baseName: String = "emp"
    val emps = List(
      new Emp(baseName + 1001, 1),
      new Emp(baseName + 1002, 2),
      new Emp(baseName + 1003, 1),
      new Emp(baseName + 1004, 2),
      new Emp(baseName + 1005, 1),
      new Emp(baseName + 1006, 2),
      new Emp(baseName + 1007, 2),
      new Emp(baseName + 1008, 1),
      new Emp(baseName + 1009, 1),
      new Emp(baseName + 1010, 1)
    )
    val deptMap: Map[Int, List[Emp]] = emps.groupBy(_.getDeptId)
    for ((deptId, empList) <- deptMap) {
      println(deptId + " >>> " + empList)
    }
  }
}

class Emp {
  @BeanProperty
  var name: String = _
  @BeanProperty
  var deptId: Int = _

  def this(name: String, deptId: Int) {
    this()
    this.name = name
    this.deptId = deptId
  }

  override def toString = s"Emp(name=$name, deptId=$deptId)"
}

執行結果:

1 >>> List(Emp(name=emp1001, deptId=1), Emp(name=emp1003, deptId=1), Emp(name=emp1005, deptId=1), Emp(name=emp1008, deptId=1), Emp(name=emp1009, deptId=1), Emp(name=emp1010, deptId=1))
2 >>> List(Emp(name=emp1002, deptId=2), Emp(name=emp1004, deptId=2), Emp(name=emp1006, deptId=2), Emp(name=emp1007, deptId=2))

相關文章