2013-05-16 2 views
3

меня есть интерфейсИспользование EnumSet из перечисления, реализующий интерфейс

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<SomeInterface>, я мог бы предотвратить этот тип ошибок (и я мог бы продолжить разработку моего класса, представляющего формальную грамматику), но я бы хотел использовать EnumSet, потому что он, вероятно, будет более эффективным, чем HashSet. Как я могу решить эту проблему?

+0

Действительно ли важна эффективность, которую вы пытаетесь использовать 'EnumSet' вместо' HashSet', или это просто ради использования 'EnumSet'? Дженерики мудрые, похоже, что в конечном итоге вы пытаетесь создать какое-то загрязнение кучи, потому что вы создали «Set» из 'Term', но пытаетесь добавить в него экземпляр «Common». –

+0

Да, теперь я понимаю, что если бы мне захотелось добавить add(), мне нужно было добавить символ EPSILON в перечисление символов терминала, но мне нужен этот символ эпсилона в общем перечислении, поэтому мне нужно использовать решение «HashSet»: D –

ответ

3

EnumSet извлекает свою эффективность из ограничения по ключевому слову, содержащего строго элементы одного перечисления. Он достигает этого, эффективно сохраняя свое состояние с опорой на ordinal номер каждого члена перечисления, в основном ведет себя как BitSet. Поэтому, к сожалению, вы не сможете воспользоваться его преимуществами, если хотите несколько перечислений.

Ближе всего вы можете достичь этой цели, разработав собственную схему нумерации, которая отличается от всех ваших перечислений, и с помощью BitSet, чтобы эффективно хранить их.

4

EnumSet может содержать только члены одного класса enum.

От Java API documentation:

Все элементы в наборе перечислений должны исходить из одного перечислимого типа, который указан, явно или неявно, когда создается множество.

Как вы заметили, альтернативой является использование Set<TerminalSymbol>.

0

EnumSet - специальная реализация интерфейса Set только для enums. Один экземпляр EnumSet может работать с конкретным перечислением только потому, что его реализация основана на ordinal перечисления.

Вы создали EnumSet для Term и попытайтесь добавить туда перечисляющий член Common. Это, очевидно, невозможно. Вы должны либо создать EnumSet для Common, либо если вы хотите сохранить элементы обоих перечислений, используйте другую реализацию Set, например. HashSet.

Смежные вопросы