java模式匹配的方式_Java 8 在类的层面实现模式匹配

1.概述

本文作为一个用例(或者说是尝试),基于 Java 8 的语法在类和方法的层面实现模式匹配的效果。考虑到对象的创建和频繁入栈和出栈,在计算密集型的代码中请谨慎使用本文中的程序。

2.Java 12 及其他语言的模式匹配

首先看下 Java 12 中 switch 表达式的效果:

int i = 0;

String s = switch (i) {

case 1 -> "1";

case 2 -> {

System.out.println("is 2");

break "2";

}

default -> "3";

};

然后是kotliln的效果:

private fun test(foo: Any): String {

var result = when (foo) {

0 -> "Object equals"

3, 10 -> "Or"

in 11..20 -> "Range contains"

is Date -> "Class instance"

!in 4..30 -> "Range not contain"

else -> "Default"

}

return result

}

再是Scala的效果:

def matchObject(foo: Any): String = {

val result = foo match {

case 0 => "Object equals"

case i if i == 10 || i == 11 => "Expression"

case i: Int => s"Class instance holds $i"

case List(1, 2, _*) => "Match the last element of a list"

case Number(n) => s"Case class holds $n"

case t: {def length: Int} => "Class structure contains method length"

case _ => "Default"

}

result

}

3.本例实现的效果

下面上本例所实现的效果:

/* API1:有返回值的匹配 */

Object o = null;//1;//4;//"ksjdf";

String s1 = Cond.match(o)

.valueOf(1, i -> "is 1")

.valueOf(2, i -> "is 2")

.typeOf(String.class, s -> "is String")

.orElse(t -> "is else");

System.out.println(s1);

/* API1:无返回值的匹配 */

o = "string";//null;//"";//1;//2;

Cond.match(o)

.valueOf(2, i -> {

System.out.println("is 2");

})

.valueOf(null, n -> System.out.println("is null"))

.typeOf(String.class, s -> System.out.println("is String"))

.orElse(t -> System.out.println("is else"));

/* 没有匹配项的情况 */

System.out.println(Cond.match(8).orElse(i -> 9999).toString());

Cond.match(8).orElse((Consumer) System.out::println);

/* API2:无返回值的匹配 */

Cond.match(8,

typeOf(String.class, t -> {

System.out.println("is string : " + t);

}),

valueOf(null, (Object obj) -> System.out.println("is null : " + obj)),

valueOf(4, (Integer t) -> System.out.println("is number " + t)),

orElse((Object i) -> System.out.println("or else" + i)));

/* API2:有返回值的匹配 */

String s2 = match(null,

typeOf(String.class, s -> "is String"),

valueOf(null, j -> "is null"),

valueOf(1, i -> "is number " + i),

orElse(obj -> "is else : " + obj))

.orElse("opt else");

System.out.println("------- " + s2);

4.代码

实现代码如下(注意,本类中包含两套API,根据喜好自行删减; 之前加了注释,发现写得可能会误导,于是就删掉了; 另外省去空指针判断,匹配的值支持null,对应操作不支持):

import java.util.Objects;

import java.util.Optional;

import java.util.function.Consumer;

import java.util.function.Function;

import java.util.function.Predicate;

public class Cond {

public static BaseCond match(T t) {

return new BaseCond<>(t);

}

@SafeVarargs

public static void match(T t, ProcCondition... conditions) {

for (ProcCondition condition : conditions) {

if (condition.predicate.test(t)) {

condition.consumer.accept(t);

return;

}

}

}

@SafeVarargs

public static Optional match(T t, FunCondition... conditions) {

for (FunCondition super T, ? extends R> condition : conditions) {

if (condition.predicate.test(t)) {

return Optional.ofNullable(condition.function.apply(t));

}

}

return Optional.empty();

}

public static class ProcCondition {

final Predicate super T> predicate;

final Consumer super T> consumer;

ProcCondition(Predicate super T> predicate, Consumer super T> consumer) {

this.predicate = predicate;

this.consumer = consumer;

}

}

public static class FunCondition {

final Predicate super T> predicate;

final Function super T, ? extends R> function;

FunCondition(Predicate super T> predicate, Function super T, ? extends R> function) {

this.predicate = predicate;

this.function = function;

}

}

public static ProcCondition typeOf(Class tClass, Consumer super K> consumer) {

return new ProcCondition<>(tClass::isInstance, t -> consumer.accept((K) t));

}

public static ProcCondition valueOf(K value, Consumer super K> consumer) {

return new ProcCondition<>(t -> Objects.equals(t, value), t -> consumer.accept((K) t));

}

public static ProcCondition orElse(Consumer super K> consumer) {

return new ProcCondition<>(t -> true, t -> consumer.accept((K) t));

}

public static FunCondition typeOf(Class tClass, Function super K, ? extends R> function) {

return new FunCondition<>(tClass::isInstance, t -> function.apply((K) t));

}

public static FunCondition valueOf(K value, Function super K, ? extends R> function) {

return new FunCondition<>(t -> Objects.equals(t, value), t -> function.apply((K) t));

}

public static FunCondition orElse(Function super K, ? extends R> function) {

return new FunCondition<>(t -> true, t -> function.apply((K) t));

}

public interface ReturnCond {

ReturnCond typeOf(Class kClass, Function super K, R> f);

ReturnCond valueOf(K value, Function super K, R> f);

R orElse(Function super T, R> f);

}

public interface VoidCond {

VoidCond typeOf(Class kClass, Consumer super K> f);

VoidCond valueOf(K value, Consumer super K> f);

void orElse(Consumer super T> f);

}

private static class EmptyReturnCond implements ReturnCond {

private final R object;

EmptyReturnCond(R object) {

this.object = object;

}

@Override

public ReturnCond typeOf(Class kClass, Function super K, R> f) {

return this;

}

@Override

public ReturnCond valueOf(K value, Function super K, R> f) {

return this;

}

@Override

public R orElse(Function super T, R> f) {

return object;

}

}

private static class ReturnCondImpl implements ReturnCond {

private final T object;

ReturnCondImpl(T object) {

this.object = object;

}

@Override

public ReturnCond typeOf(Class kClass, Function super K, R> f) {

return kClass.isInstance(object)

? new EmptyReturnCond<>(f.apply((K) object))

: this;

}

@Override

public ReturnCond valueOf(K value, Function super K, R> f) {

return Objects.equals(value, object)

? new EmptyReturnCond<>(f.apply((K) object))

: this;

}

@Override

public R orElse(Function super T, R> f) {

return f.apply(object);

}

}

private static class EmptyVoidCond implements VoidCond {

@Override

public VoidCond typeOf(Class kClass, Consumer super K> f) {

return this;

}

@Override

public VoidCond valueOf(K value, Consumer super K> f) {

return this;

}

@Override

public void orElse(Consumer super T> f) {

}

}

private static class VoidCondImpl implements VoidCond {

private final T object;

public VoidCondImpl(T object) {

this.object = object;

}

@Override

public VoidCond typeOf(Class kClass, Consumer super K> f) {

if (kClass.isInstance(object)) {

f.accept((K) object);

return new EmptyVoidCond<>();

} else {

return this;

}

}

@Override

public VoidCond valueOf(K value, Consumer super K> f) {

if (Objects.equals(value, object)) {

f.accept((K) object);

return new EmptyVoidCond<>();

} else {

return this;

}

}

@Override

public void orElse(Consumer super T> f) {

f.accept(object);

}

}

public static class BaseCond {

private final T object;

BaseCond(T object) {

this.object = object;

}

public ReturnCond typeOf(Class kClass, Function super K, R> f) {

return kClass.isInstance(object)

? new EmptyReturnCond<>(f.apply((K) object))

: new ReturnCondImpl<>(object);

}

public VoidCond typeOf(Class kClass, Consumer super K> f) {

if (kClass.isInstance(object)) {

f.accept((K) object);

return new EmptyVoidCond<>();

} else {

return new VoidCondImpl<>(object);

}

}

public ReturnCond valueOf(K value, Function super K, R> f) {

return Objects.equals(value, object)

? new EmptyReturnCond<>(f.apply((K) object))

: new ReturnCondImpl<>(object);

}

public VoidCond valueOf(K value, Consumer super K> f) {

if (Objects.equals(value, object)) {

f.accept((K) object);

return new EmptyVoidCond<>();

} else {

return new VoidCondImpl<>(object);

}

}

public void orElse(Consumer super T> f) {

f.accept(object);

}

public R orElse(Function super T, R> f) {

return f.apply(object);

}

}

}

5.总结

示例的 API1 中到达匹配条件后,后续的调用都是无效调用,匹配条件越多无效调用也越多,但是 API1 的代码更美观且使用起来更顺畅。 Android 开发中如果需要使用,則需要复制 Java 8 的个别函数式接口(Consumer,Function,Predicate),自己实现 Java 7 的 Objects 的 equals 方法,重新实现 Java 8 的 Optional 类并去掉个别 Android API 26 才能用的接口方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值