假设有一个名为Type的简单枚举,其定义如下:
enum Type{
X("S1"),
Y("S2");
private String s;
private Type(String s) {
this.s = s;
}
}
为给定的s
找到正确的枚举很简单,只需使用带有for循环的静态方法(假设该方法定义在枚举内),例如:
private static Type find(String val) {
for (Type e : Type.values()) {
if (e.s.equals(val))
return e;
}
throw new IllegalStateException(String.format("Unsupported type %s.", val));
}
我认为用Stream API表达的功能等价物是这样的:
private static Type find(String val) {
return Arrays.stream(Type.values())
.filter(e -> e.s.equals(val))
.reduce((t1, t2) -> t1)
.orElseThrow(() -> {throw new IllegalStateException(String.format("Unsupported type %s.", val));});
}
我们怎样才能写得更好更简单呢?这段代码感觉是被强迫的,并且不是很清楚。reduce()
看起来特别笨拙和滥用,因为它不积累任何东西,不执行任何计算,总是简单地返回t1
(如果过滤器返回一个值-如果不返回,那显然是一场灾难),更不用说t2
是不是多余和令人困惑的。然而,我在Stream API中找不到任何能以某种方式直接从Stream<T>
返回T
的东西。
有没有更好的方法?
发布于 2015-01-07 05:17:36
我会改用findFirst
:
return Arrays.stream(Type.values())
.filter(e -> e.s.equals(val))
.findFirst()
.orElseThrow(() -> new IllegalStateException(String.format("Unsupported type %s.", val)));
尽管在这种情况下Map
可能会更好:
enum Type{
X("S1"),
Y("S2");
private static class Holder {
static Map<String, Type> MAP = new HashMap<>();
}
private Type(String s) {
Holder.MAP.put(s, this);
}
public static Type find(String val) {
Type t = Holder.MAP.get(val);
if(t == null) {
throw new IllegalStateException(String.format("Unsupported type %s.", val));
}
return t;
}
}
我从这个answer中学到了这个技巧。基本上,类加载器在枚举类之前初始化静态类,这允许您在枚举构造函数本身中填充Map
。非常方便!
希望它能有所帮助!:)
发布于 2016-05-16 23:24:32
公认的答案运行良好,但如果您希望避免使用临时数组创建新的流,则可以使用EnumSet.allOf()
。
EnumSet.allOf(Type.class)
.stream()
.filter(e -> e.s.equals(val))
.findFirst()
.orElseThrow(String.format("Unsupported type %s.", val));
发布于 2015-01-07 05:18:04
Arrays.stream(Type.values()).filter(v -> v.s.equals(val)).findAny().orElseThrow(...);
https://stackoverflow.com/questions/27807232
复制相似问题