Java 11 Select 一种基于枚举值应用于流的方法
Java 11 Select a method to apply on a stream based on enum value
我有以下枚举。
public enum AggregationType
{
MIN,
MAX,
AVERAGE
}
让我们假设我有一个传递枚举值的函数,比如
public Float someFunction(final AggregationType enum) {
return (float) provides.stream()
.mapToDouble(this::someFunc)
.average()
.orElse(-1);
}
我想在基于枚举值的流上应用此 .average() .min() .max() 方法。
我怎样才能做到这一点?我不想在 someFunction 中使用简单的 switch 函数,而是在这个 return 语句中使用。
所以我想拥有类似
的东西
public Float someFunction(final AggregationType enum) {
return (float) provides.stream()
.mapToDouble(this::someFunc)
.decideWhichMethodShouldBeUsed()
.orElse(-1);
}
在哪里决定使用哪个方法()
根据枚举决定使用哪个函数。
何时可以将 enum
类型更改为
public enum AggregationType {
MIN(DoubleStream::min),
MAX(DoubleStream::max),
AVERAGE(DoubleStream::average);
public final Function<DoubleStream, OptionalDouble> operation;
AggregationType(Function<DoubleStream, OptionalDouble> f) {
operation = f;
}
}
你可以实现这样的方法
public Float someFunction(final AggregationType aType) {
return (float)aType.operation.apply(provides.stream().mapToDouble(this::someFunc))
.orElse(-1);
}
如果更改枚举类型不是一个选项,则必须在要实现的地方处理到实际操作的映射someFunction
,例如
private static final Map<AggregationType,Function<DoubleStream, OptionalDouble>> OPS;
static {
EnumMap<AggregationType,Function<DoubleStream, OptionalDouble>>
m = new EnumMap<>(AggregationType.class);
m.put(AggregationType.MIN, DoubleStream::min);
m.put(AggregationType.MAX, DoubleStream::max);
m.put(AggregationType.AVERAGE, DoubleStream::average);
OPS = Collections.unmodifiableMap(m);
}
public Float someFunction(final AggregationType aType) {
return (float)OPS.get(aType).apply(provides.stream().mapToDouble(this::someFunc))
.orElse(-1);
}
你也可以使用 switch
语句,但它很笨重
public Float someFunction(final AggregationType aType) {
DoubleStream ds = provides.stream().mapToDouble(this::someFunc);
OptionalDouble d;
switch(aType) {
case MAX: d = ds.max(); break;
case MIN: d = ds.min(); break;
case AVERAGE: d = ds.average(); break;
default: throw new AssertionError();
}
return (float)d.orElse(-1);
}
当你使用最近的 Java 版本时,情况会变得更好,因为那时你可以使用 switch
表达式:
public Float someFunction(final AggregationType aType) {
DoubleStream ds = provides.stream().mapToDouble(this::someFunc);
return (float)(switch(aType) {
case MAX -> ds.max();
case MIN -> ds.min();
case AVERAGE -> ds.average();
}).orElse(-1);
}
这只有在处理完所有 enum
常量后才会被编译器接受。然后,它会在幕后生成一个等价于 default -> throw new AssertionError();
的东西,它永远不会在运行时获取,只要 no-one 在这段代码编译后更改 enum
类型。
通常,只有第一个变体会迫使考虑向 AggregationType
添加新常量的开发人员也考虑处理关联的 operation
.
我有以下枚举。
public enum AggregationType
{
MIN,
MAX,
AVERAGE
}
让我们假设我有一个传递枚举值的函数,比如
public Float someFunction(final AggregationType enum) {
return (float) provides.stream()
.mapToDouble(this::someFunc)
.average()
.orElse(-1);
}
我想在基于枚举值的流上应用此 .average() .min() .max() 方法。
我怎样才能做到这一点?我不想在 someFunction 中使用简单的 switch 函数,而是在这个 return 语句中使用。
所以我想拥有类似
的东西public Float someFunction(final AggregationType enum) {
return (float) provides.stream()
.mapToDouble(this::someFunc)
.decideWhichMethodShouldBeUsed()
.orElse(-1);
}
在哪里决定使用哪个方法() 根据枚举决定使用哪个函数。
何时可以将 enum
类型更改为
public enum AggregationType {
MIN(DoubleStream::min),
MAX(DoubleStream::max),
AVERAGE(DoubleStream::average);
public final Function<DoubleStream, OptionalDouble> operation;
AggregationType(Function<DoubleStream, OptionalDouble> f) {
operation = f;
}
}
你可以实现这样的方法
public Float someFunction(final AggregationType aType) {
return (float)aType.operation.apply(provides.stream().mapToDouble(this::someFunc))
.orElse(-1);
}
如果更改枚举类型不是一个选项,则必须在要实现的地方处理到实际操作的映射someFunction
,例如
private static final Map<AggregationType,Function<DoubleStream, OptionalDouble>> OPS;
static {
EnumMap<AggregationType,Function<DoubleStream, OptionalDouble>>
m = new EnumMap<>(AggregationType.class);
m.put(AggregationType.MIN, DoubleStream::min);
m.put(AggregationType.MAX, DoubleStream::max);
m.put(AggregationType.AVERAGE, DoubleStream::average);
OPS = Collections.unmodifiableMap(m);
}
public Float someFunction(final AggregationType aType) {
return (float)OPS.get(aType).apply(provides.stream().mapToDouble(this::someFunc))
.orElse(-1);
}
你也可以使用 switch
语句,但它很笨重
public Float someFunction(final AggregationType aType) {
DoubleStream ds = provides.stream().mapToDouble(this::someFunc);
OptionalDouble d;
switch(aType) {
case MAX: d = ds.max(); break;
case MIN: d = ds.min(); break;
case AVERAGE: d = ds.average(); break;
default: throw new AssertionError();
}
return (float)d.orElse(-1);
}
当你使用最近的 Java 版本时,情况会变得更好,因为那时你可以使用 switch
表达式:
public Float someFunction(final AggregationType aType) {
DoubleStream ds = provides.stream().mapToDouble(this::someFunc);
return (float)(switch(aType) {
case MAX -> ds.max();
case MIN -> ds.min();
case AVERAGE -> ds.average();
}).orElse(-1);
}
这只有在处理完所有 enum
常量后才会被编译器接受。然后,它会在幕后生成一个等价于 default -> throw new AssertionError();
的东西,它永远不会在运行时获取,只要 no-one 在这段代码编译后更改 enum
类型。
通常,只有第一个变体会迫使考虑向 AggregationType
添加新常量的开发人员也考虑处理关联的 operation
.