使用 Java 8 Stream API 查找枚举值 [英] Finding enum value with Java 8 Stream API

查看:25
本文介绍了使用 Java 8 Stream API 查找枚举值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设有一个名为 Type 的简单枚举,定义如下:

Suppose there is a simple enum called Type defined like this:

enum Type{
    X("S1"),
    Y("S2");

    private String s;

    private Type(String s) {
        this.s = s;
    }
}

为给定的 s 找到正确的枚举是通过带有 for 循环的静态方法轻松完成的(假设该方法是在枚举中定义的),例如:

Finding the correct enum for given s is trivially done with static method with for-loop (assume the method is defined inside enum), e.g.:

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 表达的功能等价物应该是这样的:

I think the functional equivalent of this expressed with Stream API would be something like this:

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 的东西.

How could we write this better and simpler? This code feels coerced and not very clear. The reduce() especially seems clunky and abused as it doesn't accumulate anything, performs no calculation and always simply returns t1 (provided the filter returns one value - if it doesn't that's clearly a disaster), not to mention t2 is there superfluous and confusing. Yet I couldn't find anything in Stream API that simply somehow returns directly a T from a Stream<T>.

有更好的方法吗?

推荐答案

我会用 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.非常好用!

I learnt this trick from this answer. Basically the class loader initializes the static classes before the enum class, which allows you to fill the Map in the enum constructor itself. Very handy !

希望能帮到你!:)

这篇关于使用 Java 8 Stream API 查找枚举值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆