模式匹配 java_模式匹配

本文详细介绍了Java中模式匹配的使用,包括完全匹配、类型匹配、数组匹配、链表匹配、元组匹配、类匹配、偏函数、守卫、模式中的变量、提取器、变量声明中的模式以及for表达式中的模式。通过示例代码展示了如何在不同场景下进行模式匹配操作,帮助理解这一编程技巧。
摘要由CSDN通过智能技术生成

[TOC]

# 简介

与default等效的捕获所有的`case _` 模式.如果没有模式匹配,抛出MatchError,每个case中,不用break语句.可以在match中使用任何类型,而不仅仅是数字

# 完全匹配

~~~

object CaseDemo extends App {

val arr = Array("111", "222", "333")

val name = arr(Random.nextInt(arr.length))

println(name)

name match {

case "111" => println("111")

case "222" => println("222")

case _ => println("nnnnnnnn")

}

}

~~~

# 类型匹配

~~~

object CaseDemo2 extends App {

val arr = Array("hello", 1, -2.0, CaseDemo2)

val elem = arr(2)

println(elem)

elem match {

case x: Int => println("Int " + x)

case y: Double if(y>=0) => println("Double " + y)

case z: String => println("String " + z)

case CaseDemo2 => {

println("case demo 2")

}

case _ => {

println("default")

}

}

# 打印类型

println(elem.getClass.getName)

}

~~~

提示: Map类型的泛型在匹配的时候,会自动删除泛型类型,只会匹配到Map类型,而不会精确到Map里面的泛型类型

~~~

var obj = Map("a" -> 1)

obj match {

case m1: Map[String, String] => println("这是Map[String, String]")

case m2: Map[String, Int] => println("这是Map[String, Int]")

}

println(obj + " : " + obj.getClass.getName)

~~~

# 数组匹配

~~~

object CaseDemo3 extends App {

val arr = Array(0, 1, 7, 0)

arr match {

case Array(1, 5, x, y) => println(x + " " + y)

case Array(1, 1, x, y) => println("only 0")

# 匹配数组从0开始

case Array(0, _*) => println("0...")

case _ => println("something else")

}

}

~~~

# 链表匹配

~~~

object CaseDemo4 extends App {

val lst = List(0, 1)

lst match {

//Nil代表空列表 List(0)

case 0 :: Nil => println("only 0")

//s方式拼接字符串

case x :: y :: Nil => println(s"x $x y $y")

case 0 :: a => println(s"0 ... $a")

case _ => println("something else")

}

}

~~~

# 元组匹配

~~~

object CaseDemo5 extends App {

val tup = (6, 3, 5)

tup match {

case (1, x, y) => println(s"hello 123 $x, $y")

case (_, z, 5) => println(z)

case _ => println("else")

}

}

~~~

# 类匹配

~~~

//可以模式匹配

case class SubmitTask(id: String, name: String)

case class HeartBeat(time: Long)

case object CheckTimeOutTask

object CaseDemo4 extends App {

val arr = Array(CheckTimeOutTask, HeartBeat(123), HeartBeat(88888), new HeartBeat(88888), SubmitTask("0001", "task-0001"))

val a = arr(Random.nextInt(arr.length))

println(a)

a match {

case SubmitTask(id, name) => {

println(s"$id, $name")

}

case HeartBeat(time) => {

println(time)

}

case CheckTimeOutTask => {

println("check")

}

}

}

~~~

# 偏函数

被包在花括号内没有match一组case语句是一个偏函数,它是`PartialFunction[A,B]`的一个实例,A代表参数类型,B代表返回实例,常用输入模式匹配

~~~

object PartialFuncDemo {

//偏函数

def func1: PartialFunction[String, Int] = {

case "one" => 1

case "two" => 2

case _ => -1

}

//其他方式实现

def func2(num: String): Int = num match {

case "one" => 1

case "two" => 2

case _ => -1

}

def main(args: Array[String]): Unit = {

println(func1("one"))

println(func2("one"))

}

}

~~~

匿名偏函数

~~~

object CaseDemo1 extends App {

// val result = List(1, 2, 3, "heihei", 5).map{case i: Int => i * 2}

val result2 = List(1, 2, 3, "heihei", 5).collect{case i: Int => i * 2}

println(result2)

}

~~~

map不能用,因为map不会检查每个元素是不是能应用到这个函数上

函数上有类型约束的,map不检查

collect会检查

输出

~~~

List(2, 4, 6, 10)

~~~

实现策略

~~~

object CaseDemo1 extends App {

val f1 = new PartialFunction[Any, Int] {

//把类型转为Int,并加1

def apply(any: Any) = any.asInstanceOf[Int] + 1

//检查类型

def isDefinedAt(any: Any) = if (any.isInstanceOf[Int]) true else false

}

//collect会调用isDefinedAt,map不会

val result = List(1, 3, 5, "seven") collect f1

println(result)

}

~~~

# 守卫

像if表达式一样,match也提供守卫功能,守卫可以是任何boolean条件

~~~

val ch = 3

var sign = 0

ch match {

case '+' => sign = '+'

case '-' => sign = '-'

case _ if ch.toString.equals("3") => sign = 3

case _ => sign = -1

}

println(sign)

~~~

# 模式中的变量

如果在case关键字后面跟变量名,那么match前表达式的值会赋给那个变量

~~~

def match2() = {

for (c

c match {

case value if Character.isDigit(c) => println("这是一个数字: " + value)

case '+' => println("这次字符为+号")

case '-' => println("这次字符为-号")

case '*' => println("这次字符为*号")

case '/' => println("这次字符为/号")

case _ => println("通配")

}

}

}

match2()

~~~

# 提取器

模式匹配什么才算匹配呢?

即,case中unapply方法返回some集合则为匹配成功,返回none集合则为匹配失败.

**unapply**

调用unapply,传入number

接收返回值判断返回值是None还是Some

如果是Some,则将其解开,并将其中值赋值给n(就是case Square(n)中的n)

~~~

object Square {

def unapply(z: Double): Option[Double] = Some(math.sqrt(z))

}

object CaseDemo2 extends App {

var n = 36.0

n match {

case Square(result) => println(s" ${n} + ",s" + ${result}")

}

}

~~~

输出

~~~

( 36.0 + , + 6.0)

~~~

# 变量声明中的模式

match中每一个case都可以单独提取出来,意思是一样的

~~~

val (x, y) = (1, 2)

println(x, y)

val (q, r) = BigInt(10) /% 3

println(q, r)

val arr = Array(1, 7, 2, 9)

val Array(first, second, _*) = arr

println(first, second)

~~~

输出

~~~

(1,2)

(3,1)

(1,7)

~~~

# for表达式中的模式

~~~

import scala.collection.JavaConverters._

for ((k, v)

println(k + " -> " + v)

}

~~~

# 中置表达式

什么是一个中置表达式? 1+2,这就是一个中置表达式.

如果unapply方法产出一个元组,你可以在case语句中使用中置表示法.比如可以匹配一个List序列

~~~

val list = List(1, 2, 3, 4, 5, 6)

list match {

case l1 :: l2 :: l3 => println(l1 + " , " + l2 + " , " + l3)

}

~~~

从左到有,多的就变为list

输出

~~~

1 , 2 , List(3, 4, 5, 6)

~~~

# 嵌套类

~~~

abstract class Item

case class Article(description: String, price: Double) extends Item

//Item*表示可以多个

case class Bundle(description: String, discount: Double, item: Item*) extends Item

object CaseDemo extends App {

def match9() = {

val sale = Bundle("愚人节大甩卖系列", 10,

Article("<>", 40),

Bundle("从出门一条狗到装备全发光", 20,

Article("如何快速捡起地上装备", 80),

Article("名字起的太长", 30)))

val result = sale match {

case Bundle(_, _, Article(descr, _), _*) => descr

}

println(result)

}

match9()

}

~~~

输出

~~~

<>

~~~

如果要输出后面可以这样

~~~

val result = sale match {

case Bundle(_, _, Article(descr, _), temp @ _*) => temp

}

~~~

输出

~~~

WrappedArray(Bundle(从出门一条狗到装备全发光,20.0,WrappedArray(Article(如何快速捡起地上装备,80.0), Article(名字起的太长,30.0))))

~~~

通过@表示法将嵌套的值绑定到变量

`_*`绑定剩余Item到temp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值