使用 Java 8 Stream API 查找枚举值

新手上路,请多包涵

假设有一个名为 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 中找不到任何以某种方式直接从 T 直接返回 Stream<T> 的内容。

有没有更好的办法?

原文由 quantum 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 688
2 个回答

我会使用 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;
    }
}

我从这个 答案 中学到了这个技巧。基本上,类加载器在枚举类之前初始化静态类,这允许您在枚举构造函数本身中填充 Map 。非常便利 !

希望能帮助到你 ! :)

原文由 Alexis C. 发布,翻译遵循 CC BY-SA 3.0 许可协议

接受的答案效果很好,但如果您想避免使用临时数组创建新流,您可以使用 EnumSet.allOf()

 EnumSet.allOf(Type.class)
       .stream()
       .filter(e -> e.s.equals(val))
       .findFirst()
       .orElseThrow(() -> new IllegalStateException(String.format("Unsupported type %s.", val)));

原文由 Pär Eriksson 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题