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<Integer>) 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 <T> BaseCond<T> match(T t) {
        return new BaseCond<>(t);
    }

    @SafeVarargs
    public static <T> void match(T t, ProcCondition<T>... conditions) {
        for (ProcCondition<T> condition : conditions) {
            if (condition.predicate.test(t)) {
                condition.consumer.accept(t);
                return;
            }
        }
    }

    @SafeVarargs
    public static <T, R> Optional<R> match(T t, FunCondition<T, R>... 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<T> {
        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<T, R> {
        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 <T, K> ProcCondition<T> typeOf(Class<K> tClass, Consumer<? super K> consumer) {
        return new ProcCondition<>(tClass::isInstance, t -> consumer.accept((K) t));
    }

    public static <T, K> ProcCondition<T> valueOf(K value, Consumer<? super K> consumer) {
        return new ProcCondition<>(t -> Objects.equals(t, value), t -> consumer.accept((K) t));
    }

    public static <T, K> ProcCondition<T> orElse(Consumer<? super K> consumer) {
        return new ProcCondition<>(t -> true, t -> consumer.accept((K) t));
    }

    public static <T, K, R> FunCondition<T, R> typeOf(Class<K> tClass, Function<? super K, ? extends R> function) {
        return new FunCondition<>(tClass::isInstance, t -> function.apply((K) t));
    }

    public static <T, R, K> FunCondition<T, R> valueOf(K value, Function<? super K, ? extends R> function) {
        return new FunCondition<>(t -> Objects.equals(t, value), t -> function.apply((K) t));
    }

    public static <T, K, R> FunCondition<T, R> orElse(Function<? super K, ? extends R> function) {
        return new FunCondition<>(t -> true, t -> function.apply((K) t));
    }

    public interface ReturnCond<T, R> {
        <K> ReturnCond<T, R> typeOf(Class<K> kClass, Function<? super K, R> f);

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

        R orElse(Function<? super T, R> f);
    }

    public interface VoidCond<T> {
        <K> VoidCond<T> typeOf(Class<K> kClass, Consumer<? super K> f);

        <K> VoidCond<T> valueOf(K value, Consumer<? super K> f);
        
        void orElse(Consumer<? super T> f);
    }

    private static class EmptyReturnCond<T, R> implements ReturnCond<T, R> {
        private final R object;

        EmptyReturnCond(R object) {
            this.object = object;
        }

        @Override
        public <K> ReturnCond<T, R> typeOf(Class<K> kClass, Function<? super K, R> f) {
            return this;
        }

        @Override
        public <K> ReturnCond<T, R> 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<T, R> implements ReturnCond<T, R> {
        private final T object;

        ReturnCondImpl(T object) {
            this.object = object;
        }

        @Override
        public <K> ReturnCond<T, R> typeOf(Class<K> kClass, Function<? super K, R> f) {
            return kClass.isInstance(object)
                    ? new EmptyReturnCond<>(f.apply((K) object))
                    : this;
        }

        @Override
        public <K> ReturnCond<T, R> 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<T> implements VoidCond<T> {

        @Override
        public <K> VoidCond<T> typeOf(Class<K> kClass, Consumer<? super K> f) {
            return this;
        }

        @Override
        public <K> VoidCond<T> valueOf(K value, Consumer<? super K> f) {
            return this;
        }

        @Override
        public void orElse(Consumer<? super T> f) {

        }
    }

    private static class VoidCondImpl<T> implements VoidCond<T> {
        private final T object;

        public VoidCondImpl(T object) {
            this.object = object;
        }

        @Override
        public <K> VoidCond<T> typeOf(Class<K> kClass, Consumer<? super K> f) {
            if (kClass.isInstance(object)) {
                f.accept((K) object);
                return new EmptyVoidCond<>();
            } else {
                return this;
            }
        }

        @Override
        public <K> VoidCond<T> 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<T> {
        private final T object;

        BaseCond(T object) {
            this.object = object;
        }

        public <K, R> ReturnCond<T, R> typeOf(Class<K> kClass, Function<? super K, R> f) {
            return kClass.isInstance(object)
                    ? new EmptyReturnCond<>(f.apply((K) object))
                    : new ReturnCondImpl<>(object);
        }

        public <K> VoidCond<T> typeOf(Class<K> kClass, Consumer<? super K> f) {
            if (kClass.isInstance(object)) {
                f.accept((K) object);
                return new EmptyVoidCond<>();
            } else {
                return new VoidCondImpl<>(object);
            }
        }

        public <K, R> ReturnCond<T, R> valueOf(K value, Function<? super K, R> f) {
            return Objects.equals(value, object)
                    ? new EmptyReturnCond<>(f.apply((K) object))
                    : new ReturnCondImpl<>(object);
        }

        public <K> VoidCond<T> 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> 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 才能用的接口方法。

发布了16 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/zssrxt/article/details/91350493