问题Switch over type in java考虑了如何根据对象的类型打开要执行的代码。
现在,我想以一种在多种功能语言中使用的方式来声明case
:
r = case x of
String s -> s
Int i -> toString i
也就是说,我要打开类型,还要将switch语句视为一个表达式(即它应该有一个结果)。
就像在开关中一样,应该允许多个案例匹配,但是评估将从头到尾进行检查,并返回第一个匹配的值(如果没有匹配,则返回null)。
对于上述使用Java 8功能特性的问题,其格式可能为this answer:
switchType(x,
caze(String.class, v -> print("String: " + v),
caze(Integer.class, v -> print("Int: " + v));
答案 0 :(得分:3)
类似于this answer中的适应通过仅执行第一个匹配来适应上述解决方案,可以为返回类型添加一个附加类型参数R
并使用Function<T,R>
代替Predicate<T>
:
public static <R> R caseType(Object obj, Function<Object, Optional<R>>... functions) {
for (Function<Object, Optional<R>> f : functions) {
Optional<R> res = f.apply(obj);
if (res.isPresent()) {
return res.get();
}
}
return null; // Default case (no match)
}
public static <T, R> Function<Object, Optional<R>> of(Class<T> cls, Function<T, R> f) {
// Wrap the function with a type check
return obj -> {
if (cls.isInstance(obj)) {
return Optional.of(f.apply((T) obj)); // As we must return a function taking an Object, we have to convert here
} else {
return Optional.empty();
}
};
}
以下示例演示了用法和行为:
String s = "Hello World";
Integer i = 5;
Double d = 1.0 / 3;
Object x = s;
Object y = i;
Object z = d;
String res1 = caseType(x,
of(String.class, v -> v.substring(0, 5)),
of(Integer.class, v -> String.format("%d", v)),
of(Double.class, v -> String.format("%1.4f", v)));
String res2 = caseType(y,
of(String.class, v -> v.substring(0, 5)),
of(Integer.class, v -> String.format("%d", v)),
of(Double.class, v -> String.format("%1.4f", v)));
String res3 = caseType(z,
of(String.class, v -> v.substring(0, 5)),
of(Integer.class, v -> String.format("%d", v)),
of(Double.class, v -> String.format("%1.4f", v)));
String firstMatch = caseType(x,
of(String.class, v -> "first case"),
of(String.class, v -> "second case"));
String resNull = caseType(z,
of(String.class, v -> v.substring(0, 5)),
of(Integer.class, v -> String.format("%d", v)));
String resDefault = caseType(z,
of(String.class, v -> v.substring(0, 5)),
of(Integer.class, v -> String.format("%d", v)),
of(Object.class, v -> "unknown"));
String resSubtype1 = caseType(y,
of(Number.class, v -> String.format("%1.4f", v.doubleValue())),
of(Object.class, v -> "unknown"));
String resSubtype2 = caseType(z,
of(Number.class, v -> String.format("%1.4f", v.doubleValue())),
of(Object.class, v -> "unknown"));
System.out.println("res1: " + res1);
System.out.println("res2: " + res2);
System.out.println("res3: " + res3);
System.out.println("firstMatch: " + firstMatch);
System.out.println("resNull: " + resNull);
System.out.println("resDefault: " + resDefault);
System.out.println("resSubtype1: " + resSubtype1);
System.out.println("resSubtype2: " + resSubtype2);
输出:
res1: Hello
res2: 5
res3: 0.3333
firstMatch: first case
resNull: null
resDefault: unknown
resSubtype1: 5.0000
resSubtype2: 0.3333
如果希望结果为Optional
(如果有匹配项则为值,如果没有匹配项则为空),则可以相应地调整大小写功能:
private static <R> Optional<R> caseTypeNonNull(Object obj, Function<Object, Optional<R>>... functions) {
for (Function<Object, Optional<R>> f : functions) {
Optional<R> res = f.apply(obj);
if (res.isPresent()) {
return Optional.of(res.get());
}
}
return Optional.empty(); // Default case (no match)
}