【问题标题】:Using EnumSet of a enum implementing an interface使用实现接口的枚举的 EnumSet
【发布时间】:2013-05-11 19:17:42
【问题描述】:

我有一个界面

public interface TerminalSymbol {
    // methods ...
}

一个枚举

// common usage enum that I need
public enum Common implements TerminalSymbol {
    EPSILON;

    @Override
    // methods ...
}

我想做一些类似的事情:

enum Term implements TerminalSymbol {
    A, B, C, ...

    @Override
    // methods ...
}

EnumSet<? extends TerminalSymbol> terminalSymbols = EnumSet.allOf(Term.class);
terminalSymbol.add(Common.EPSILON); // this line gives me error

那个错误是(在我的例子中):

The method add(capture#1-of ? extends TerminalSymbol) in the type AbstractCollection<capture#1-of ? extends TerminalSymbol> is not applicable for the arguments (Common)

现在我知道,如果我使用 Set&lt;SomeInterface&gt;,我可以防止这种类型的错误(并且我可以继续开发代表正式语法的类)但我想使用 EnumSet,因为它可能比HashSet 更有效率。我该如何解决这个问题?

【问题讨论】:

  • 您尝试使用EnumSet 而不是HashSet 是否真的对效率至关重要,或者仅仅是为了使用EnumSet?从泛型角度来看,您最终似乎是在尝试创建一些堆污染,因为您已经创建了 Terms 的 Set,但正在尝试将 Common 的实例添加到其中。
  • 是的,现在我意识到如果我想做 add() 我需要在终端符号的枚举中添加 EPSILON 符号,但我需要在公共枚举中使用这个 epsilon 符号所以我必须使用HashSet 解决方案:D

标签: java enums enumset


【解决方案1】:

EnumSet 的效率源于它严格包含单个枚举成员的键约束。它通过依赖每个枚举成员的ordinal 数量有效地存储其状态来实现这一点,基本上表现得像BitSet。所以不幸的是,如果你想要多个枚举,你将无法获得它的好处。

最接近此目标的方法是设计自己的编号方案,该方案在所有枚举中都不同,并使用BitSet 有效地存储它们。

【讨论】:

    【解决方案2】:

    EnumSetSet 接口的特殊实现,仅用于enumsEnumSet 的一个实例只能使用特定的枚举,因为它的实现是基于枚举的ordinal

    您为Term 创建了EnumSet,并尝试添加Common 的枚举成员。这显然是不可能的。您应该为Common 创建EnumSet,或者如果您想在其中存储两个枚举的元素,请使用Set 的其他实现,例如HashSet.

    【讨论】:

      【解决方案3】:

      EnumSet 只能包含一个枚举类的成员。

      来自Java API documentation

      枚举集合中的所有元素必须来自一个枚举类型,该枚举类型在创建集合时显式或隐式指定。

      如您所述,另一种方法是使用Set&lt;TerminalSymbol&gt;

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-28
        • 2016-09-03
        • 1970-01-01
        • 1970-01-01
        • 2019-06-03
        • 1970-01-01
        • 2011-02-12
        相关资源
        最近更新 更多