背景
最近在看kafka原始碼發現,kafka
中scala
語法用到了大量的模式匹配,所以就來簡單研究下scala
的模式匹配
java switch使用
int xiaozou = 1; switch (xiaozou) { case 1: System.out.println("xiaozou = 1"); break; case 2: System.out.println("xiaozou = 2"); break; default: System.out.println("xiaozou = default"); } }
java
的Switch
用法比較簡單,也只能做到上面這種簡單的判斷,只支援單資料型別
scala模式匹配
首先我們來看一個基礎資料型別的例子
def main(args: Array[String]): Unit = { println(describe(42)) println(describe(-10)) println(describe("hello")) println(describe(List(1,2,3,4))) println(describe(Some("test"))) println(describe(None)) println(describe(3.14)) } def describe(x: Any): String = x match { case i: Int if i > 0 => s"Positive number: $i" case i: Int if i < 0 => s"Negative number: $i" case s: String => s"String with length ${s.length}" case list: List[_] if list.length > 3 => s"Long list of integers, first element: ${list.head}" case Some(value) => s"Some with value: $value" case None => "None" case _ => "Something else" }
執行結果
Positive number: 42 Negative number: -10 String with length 5 Long list of integers, first element: 1 Some with value: test None Something else
可以看到這裏的模式匹配比java
的switch
要強大很多,可以匹配任何型別的資料,然後能做一些複雜的判斷
對於自定義型別,也是可以實現很強大的模式匹配
def main(args: Array[String]): Unit = { println(describeClass(XiaoZou("小奏", 15))) println(describeClass(XiaoZou("大奏", 25))) println(describeClass(Language("Max", "Labrador"))) println(describeClass(Language("Buddy", "Beagle"))) } def describeClass(clazz: Any): String = clazz match { case XiaoZou(name, age) if age < 18 => s"$name is a minor" case XiaoZou(name, age) => s"$name is an adult" case Language(name, "Java") => s"$name 比較熟悉" case Language(name, _) => s"$name 一般熟悉" case _ => "Unknown language" } case class XiaoZou(name: String, age: Int) case class Language(name: String, version: String)
執行結果
小奏 is a minor 大奏 is an adult Java 一般熟悉 Go 一般熟悉
可以看到scala
中的模式匹配可以提取出物件的屬性,然後進行一些複雜的條件判斷
kafka中的模式匹配使用
kafka
中大量使用了scala
語法,模式匹配很場景,kafka
最核心最終要的原始碼類KafkaApis
對不同的網路請求處理就使用了模式匹配去處理
我們再看看如果沒有使用模式匹配對於這些case 用java 是如何處理的,我們這裏看看RocketMQ
這一快的原始碼
其實這一部分來看不出來太大的語法差異,主要就是scala
不需要顯式的break
值得注意的是jdk17也支援了類似的功能,比如像如下
String day = "MONDAY"; String result = switch (day) { case "MONDAY", "FRIDAY", "SUNDAY" -> "休息日"; case "TUESDAY" -> "工作日"; case "THURSDAY", "SATURDAY" -> "學習日"; case "WEDNESDAY" -> "購物日"; default -> "未知"; };
總結
總的來說scala
的模式匹配比java的switch
強很多,具體表現如下幾個方面
可以匹配幾乎任何型別的資料,包括複雜物件、集合和自定義型別
可以解構複雜物件,提取其中的欄位或元素
可以包含複雜的條件邏輯,如型別檢查、值範圍檢查等
通常沒有落空行為,每個case都是獨立的,不需要顯式的break
但是隨著jdk的慢慢升級,一些scala
的語法都在慢慢支援