首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用Java 8 Stream API查找枚举值

使用Java 8 Stream API查找枚举值
EN

Stack Overflow用户
提问于 2015-01-07 05:10:48
回答 8查看 80.8K关注 0票数 42

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

代码语言:javascript
复制
enum Type{
    X("S1"),
    Y("S2");

    private String s;

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

为给定的s找到正确的枚举很简单,只需使用带有for循环的静态方法(假设该方法定义在枚举内),例如:

代码语言:javascript
复制
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表达的功能等价物是这样的:

代码语言:javascript
复制
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的东西。

有没有更好的方法?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2015-01-07 05:17:36

我会改用findFirst

代码语言:javascript
复制
return Arrays.stream(Type.values())
            .filter(e -> e.s.equals(val))
            .findFirst()
            .orElseThrow(() -> new IllegalStateException(String.format("Unsupported type %s.", val)));

尽管在这种情况下Map可能会更好:

代码语言:javascript
复制
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。非常方便!

希望它能有所帮助!:)

票数 89
EN

Stack Overflow用户

发布于 2016-05-16 23:24:32

公认的答案运行良好,但如果您希望避免使用临时数组创建新的流,则可以使用EnumSet.allOf()

代码语言:javascript
复制
EnumSet.allOf(Type.class)
       .stream()
       .filter(e -> e.s.equals(val))
       .findFirst()
       .orElseThrow(String.format("Unsupported type %s.", val));
票数 20
EN

Stack Overflow用户

发布于 2015-01-07 05:18:04

代码语言:javascript
复制
Arrays.stream(Type.values()).filter(v -> v.s.equals(val)).findAny().orElseThrow(...);
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27807232

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档