简体   繁体   English

在Java中如何编写代码循环遍历枚举?

[英]In Java how do write code to loop round an arbitary enum?

How do write code to loop round an arbitary enum ? 如何编写代码循环任意枚举?

So in the code below in use an enum as the values to provide to create a Html select loop, but I cannot see how to pass an enum to the method, or how to access the standard .values() and .ordinal() methods. 因此,在下面的代码中使用枚举作为提供创建Html select循环的值,但是我看不到如何将枚举传递给方法,或者如何访问标准的.values().ordinal()方法。 so currently I have hardcoded a particular enum RenameFileOptions but I want to work with any enum, I could parse enum class eg RenameFileOptions.class but still how would I access .name() , .values() and .ordinal() 所以目前我已经对特定的枚举RenameFileOptions进行了硬编码,但是我想使用任何枚举,我可以解析枚举类,例如RenameFileOptions.class但仍然如何访问.name() .values().ordinal()

public ContainerTag addCombo(UserOption userOption, int selectedValue)
{
    return div(
                label(userOption.getLabel().getMsg())
                    .withTitle(userOption.getTooltip().getMsg()),
                select(
                    each(Arrays.asList(RenameFileOptions.values()),
                            next ->
                                iffElse(next.ordinal()==selectedValue,
                                        option(next.name()).attr(Html.SELECTED, Html.SELECTED).withValue(String.valueOf(next.ordinal())),
                                        option(next.name()).withValue(String.valueOf(next.ordinal()))
                                )
                    ))
                .withName(userOption.getOption())
            );
}

Update As there seemed to be no way to achieve this in a none hacky way I instead added a getOptions() methods to each enum, and this is what is sent to my addCombo method. 更新由于似乎没有办法以一种轻松的方式实现这一目标,所以我向每个枚举添加了一个getOptions()方法,这就是发送给我的addCombo方法的内容。 It means I have to essentially repeat code, which I dont like doing but it means the addCombo() method works as required and keeps the code easier to understand by not introducing difficult syntax. 这意味着我必须重复执行我不喜欢做的代码,但这意味着addCombo()方法可以按要求工作,并且通过不引入困难的语法来使代码更易于理解。

public enum RenameFileOptions implements OptionList
{
    NO(TextLabel.RENAME_FILE_OPTION_NO),
    YES_IF_MATCHED_TO_RELEASE(TextLabel.RENAME_FILE_OPTION_YES_IF_RELEASE_MATCH),
    YES_IF_MATCHED_TO_RELEASE_OR_SONG(TextLabel.RENAME_FILE_OPTION_YES_IF_RELEASE_OR_SONG_MATCH),
    YES_IF_HAS_BASIC_METADATA(TextLabel.RENAME_FILE_OPTION_YES_IF_HAS_METADATA),
    YES_FOR_ALL_SONGS(TextLabel.RENAME_FILE_OPTION_YES),

    ;
    private TextLabel label;

    RenameFileOptions(TextLabel label)
    {
        this.label=label;
    }

    public String getName()
    {
        return label.getMsg();
    }

    public String toString()
    {
        return getName();
    }

    public static List<NameKey> getOptions()
    {
        List<NameKey> options = new ArrayList<NameKey>();
        for(RenameFileOptions next:RenameFileOptions.values())
        {
            options.add(new NameKey(next.ordinal(), next.getName()));
        }
        return options;
    }
}

public class NameKey
{
    private Integer id;
    private String name;

    public NameKey(Integer id, String name)
    {
        this.id =id;
        this.name=name;
    }
    public Integer getId()
    {
        return id;
    }

    public void setId(Integer id)
    {
        this.id = id;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }
}

You should use Class.getEnumConstants() method. 您应该使用Class.getEnumConstants()方法。

So, middle part of your code should be something like 因此,您的代码的中间部分应类似于

                each(Arrays.asList(enumClass.getEnumConstants()),
                        next ->
                            iffElse(next.ordinal()==selectedValue,
                                    option(next.name()).attr(Html.SELECTED, Html.SELECTED).withValue(String.valueOf(next.ordinal())),
                                    option(next.name()).withValue(String.valueOf(next.ordinal()))
                            )
                ))

and you should pass Class<? extends Enum<?>> enumClass 并且您应该通过Class<? extends Enum<?>> enumClass Class<? extends Enum<?>> enumClass in method parameters. 在方法参数中Class<? extends Enum<?>> enumClass

You can use EnumSet.allOf() : 您可以使用EnumSet.allOf()

for(MyType t : EnumSet.allOf(MyType.class)) {
    doSomethingWith(t);
}

... or with Java 8 lambdas: ...或使用Java 8 lambda:

EnumSet.allOf(MyType.class).forEach( 
    t -> doSomethingWith(t)
);

Despite being a Set , EnumSet 's documentation states that its iterator yields values "in their natural order (the order in which the enum constants are declared)" 尽管是Set ,但EnumSet的文档指出其迭代器产生的值“以其自然顺序 (声明枚举常量的顺序)”


For an arbitarary enum class: 对于任意枚举类:

<T extends Enum<T>> void loopAroundEnum(Class<T> enumType) {
    EnumSet.allOf(enumType).forEach(
       val -> doSomethingWith(val) // val is of type T
    );
}

Although the Java habit is to not optimise prematurely, it's worth knowing that an EnumSet is probably more efficient both in speed and in memory consumption than using the MyType[] array returned by MyType.getEnumConstants() . 尽管Java习惯是不进行过早优化,但值得一提的是,与使用MyType.getEnumConstants()返回的MyType[]数组相比, EnumSet 可能在速度和内存消耗上都更有效率。

From EnumSet 's Javadoc: EnumSet的Javadoc:

Enum sets are represented internally as bit vectors. 枚举集在内部表示为位向量。 This representation is extremely compact and efficient. 这种表示非常紧凑和高效。 The space and time performance of this class should be good enough to allow its use as a high-quality, typesafe alternative to traditional int-based "bit flags." 该类的时空性能应足够好,可以用作传统的基于int的“位标志”的高质量,类型安全的替代方法。

As Enum is the base class, and you need to pass a Class to an enum: 由于Enum是基类,因此您需要将Class传递给枚举:

public <E extends Enum<E>> void method(Class<E> type) {
    E[] values = type.getEnumConstants();
}

Of course Class has a test whether it is an enum; 当然,Class会测试它是否为枚举。 it returns null when no enum class. 如果没有枚举类,则返回null。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM