-1

I want to create a Map<Long, Enum< ? extends SomeInterface>. Which is the best option for me?

I tried this one

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())));

But it is giving error "cannot convert from Map<Object,Object> to Map<Long,Enum<? extends SomeEnum>[]>". I am new to this. Please help!

I need unmodifiable map of question Id to the corrosponding possible answers values. Possible answers are Enums

Possible Answers are wrapped like this :

public class RecognizedAnswers {
public enum AnswerEnum1 implements SomeInterface;
public enum Answer2 implements SomeInterface;
 }
user3681970
  • 1,201
  • 4
  • 19
  • 37
  • So for each QuestionId, there is the same AnswerEnum set, of they differ? – Beri Apr 09 '17 at 07:19
  • They are different. Each AnswerEnum extends SomeEnum – user3681970 Apr 09 '17 at 07:20
  • But it does not sum up. In your example you have a collection of answers, and according to the description you need to map single QuestioId to single Answer – Beri Apr 09 '17 at 07:23
  • I updated the question. Since i changed the variable names before posting the question, i have missed that point. Each AnswerEnum extends SomeEnum – user3681970 Apr 09 '17 at 07:25
  • 1
    In Java it's not possible to extend an enum I think – Alexander Kulyakhtin Apr 09 '17 at 07:35
  • that is correct, @AlexanderKulyakhtin – Sharon Ben Asher Apr 09 '17 at 07:37
  • @AlexanderKulyakhtin yes.. it is an interface. I have updated the question. The answer below still gives the same error mentioned in question. Please help! – user3681970 Apr 09 '17 at 08:16
  • Note that it actually *is* possible to extend an enum (though only inside the enum definition itself). "constant-specific method implementations" (discussed in Effective Java: Item 30) cause the enum constants to *extend* the enum type, meaning that `MyEnum.getClass().equals(MyEnum.VALUE.getClass()` can sometimes return false. Here's an [example](http://stackoverflow.com/q/28396713/113632) from a SO question. – dimo414 Apr 11 '17 at 07:41

2 Answers2

1

There is a small problem with naming I think:

You cannot extend one enum with another in java, use interface with desired method instead, like below

And below code is working fine:

   @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 {

    }
Beri
  • 11,470
  • 4
  • 35
  • 57
  • Thanks! The point is All QuestionEnums are wrapped in a class. I have updated the question. The above code gives the same error mentioned in question – user3681970 Apr 09 '17 at 07:49
0

I tried to replicate your example (since you obfuscated the enum types, I made up my own) and it appears to compile just fine:

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)));

My guess is that you have either a missing parenthesis, or your QuestionEnum1.getQuestionId() returns an int rather than a long, and those things are confusing the compiler enough that it can't give a clear error message.

I'll note that the Stream API really isn't a clean way to construct a constant map. Simply building such a map "normally" with Map.put() will likely be simpler and easier to read, even if it requires a static {} block or a helper function. You can do even better with Guava's immutable collections, which could be used like so:

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();

Much clearer and easier to read (and write).

dimo414
  • 47,227
  • 18
  • 148
  • 244