Путаница в выборе структуры данных

Я хочу создать Map<Long, Enum< ? extends SomeInterface>. Какой лучший вариант для меня?

я попробовал этот

private Map<Long, Enum<? extends SomeInterface>[]> questionIdToanswersMapping = Collections.unmodifiableMap(Stream.of(
        new SimpleEntry<>(QuestionEnum1.getQuestionId(), AnswerEnum1.values()),
        new SimpleEntry<>(QuestionEnum2.getQuestionId(), AnswerEnum2.values()),
        new SimpleEntry<>(QuestionEnum3.getQuestionId(), AnswerEnum3.values()),
        new SimpleEntry<>(QuestionEnum4.getQuestionId(), AnswerEnum4.values()),
        new SimpleEntry<>(QuestionEnum5.getQuestionId(), AnswerEnum5.values()))
.collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue())));

Но выдает ошибку "невозможно преобразовать из Map<Object,Object> в Map<Long,Enum<? extends SomeEnum>[]>". Я новичок в этом. Пожалуйста помоги!

Мне нужна неизменяемая карта идентификатора вопроса с соответствующими возможными значениями ответов. Возможные ответы: Enums

Возможные ответы завернуты следующим образом:

public class RecognizedAnswers {
public enum AnswerEnum1 implements SomeInterface;
public enum Answer2 implements SomeInterface;
 }

person user3681970    schedule 09.04.2017    source источник
comment
Итак, для каждого QuestionId существует один и тот же набор AnswerEnum, отличаются ли они?   -  person Beri    schedule 09.04.2017
comment
Они разные. Каждый AnswerEnum расширяет SomeEnum   -  person user3681970    schedule 09.04.2017
comment
Но это не итог. В вашем примере у вас есть набор ответов, и, согласно описанию, вам нужно сопоставить один QuestioId с одним ответом.   -  person Beri    schedule 09.04.2017
comment
Я обновил вопрос. Поскольку я изменил имена переменных перед публикацией вопроса, я пропустил этот момент. Каждый AnswerEnum расширяет SomeEnum   -  person user3681970    schedule 09.04.2017
comment
В Java невозможно расширить перечисление, я думаю   -  person Alexander Kulyakhtin    schedule 09.04.2017
comment
правильно, @AlexanderKulyakhtin   -  person Sharon Ben Asher    schedule 09.04.2017
comment
@АлександрКуляхтин да .. это интерфейс. Я обновил вопрос. Ответ ниже по-прежнему дает ту же ошибку, о которой идет речь. Пожалуйста помоги!   -  person user3681970    schedule 09.04.2017
comment
Обратите внимание, что на самом деле можно расширить перечисление (но только внутри самого определения перечисления). Реализации методов, специфичных для констант (обсуждаемые в разделе «Эффективная Java: статья 30»), приводят к тому, что константы перечисления расширяют тип перечисления, а это означает, что MyEnum.getClass().equals(MyEnum.VALUE.getClass() иногда может возвращать значение false. Вот пример из вопроса SO.   -  person dimo414    schedule 11.04.2017


Ответы (2)


Я думаю, есть небольшая проблема с именованием:

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

И ниже код работает нормально:

   @Test
    public void test() {
        Map<Long, Enum<? extends SomeEnum>[]> questionIdToanswersMapping = Collections.unmodifiableMap(Stream.of(
                new AbstractMap.SimpleEntry<>(QuestionEnum1.A.getQuestionId(), AnswerEnum1.values()),
                new AbstractMap.SimpleEntry<>(QuestionEnum1.B.getQuestionId(), AnswerEnum1.values()),
                new AbstractMap.SimpleEntry<>(QuestionEnum1.C.getQuestionId(), AnswerEnum2.values()),
                new AbstractMap.SimpleEntry<>(QuestionEnum1.D.getQuestionId(), AnswerEnum2.values())
                )
                .collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue())));

        System.out.print(questionIdToanswersMapping.size());
    }

    enum QuestionEnum1 {
        A, B, C, D;

        Long getQuestionId() {
            return (long) name().hashCode(); // my mocked values
        }

    }

    interface SomeEnum {

    }

    enum AnswerEnum1 implements SomeEnum {

    }
    enum AnswerEnum2 implements SomeEnum {

    }
person Beri    schedule 09.04.2017
comment
Спасибо! Дело в том, что все QuestionEnums завернуты в класс. Я обновил вопрос. Приведенный выше код дает ту же ошибку, о которой идет речь. - person user3681970; 09.04.2017

Я попытался воспроизвести ваш пример (поскольку вы запутали типы перечислений, я придумал свой собственный), и, похоже, он отлично компилируется:

enum SomeEnum { FOO, BAR }

private Map<Long, Enum<? extends SomeEnum>[]> exampleMap =
    Collections.unmodifiableMap(Stream.of(
        new SimpleEntry<>(1L, SomeEnum.values()))
      .collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue)));

Я предполагаю, что у вас либо пропущена скобка, либо ваш QuestionEnum1.getQuestionId() возвращает int, а не long, и эти вещи настолько запутывают компилятор, что он не может выдать четкое сообщение об ошибке.

Я отмечу, что Stream API действительно не является чистым способом создания постоянной карты. Простое построение такой карты «обычно» с помощью Map.put(), вероятно, будет проще и легче читать, даже если для этого потребуется блок static {} или вспомогательная функция. Вы можете добиться еще большего успеха с Guava неизменяемые коллекции, которые можно использовать следующим образом:

private final ImmutableMap<Long, Enum<? extends SomeEnum>[]> questionIdToanswersMapping =
    ImmutableMap.builder()
        .put(QuestionEnum1.getQuestionId(), AnswerEnum1.values())
        .put(QuestionEnum2.getQuestionId(), AnswerEnum2.values())
        .put(QuestionEnum3.getQuestionId(), AnswerEnum3.values())
        .put(QuestionEnum4.getQuestionId(), AnswerEnum4.values())
        .put(QuestionEnum5.getQuestionId(), AnswerEnum5.values())
        .build();

Намного понятнее и легче читать (и писать).

person dimo414    schedule 09.04.2017