2

I have several enums that implement the interface Word. I want to generate a list of all of the values of these enums.

The way I am currently doing this is:

    public Set<Word> allWords() {
        Set<Word> dictionary = new HashSet<>();
        dictionary.addAll(Arrays.asList(Article.values()));
        dictionary.addAll(Arrays.asList(Conjunction.values()));
        dictionary.addAll(Arrays.asList(Verb.values()));
        // And so on...
        return dictionary;
    }

Is there a way to iterate over these enums? I imagine it would involve creating a list of Class objects, but I'm not sure how to convert that back the the actual values.

In case it's relevant, Word and each of the enums are in the same package (lexicon).

DwB
  • 37,124
  • 11
  • 56
  • 82
  • Why do you ask how iterate? You have code that built a set of `Word`. Just loop that set. – Basil Bourque Dec 09 '21 at 20:27
  • @roccobaroccoSC The interface contains a method (getWord) that each enum implements, which allows the retrieval of the string literal it represents, as some of them include illegal characters for an enum (such as "and/or"). The question is about whether I can use reflection to get a list of all the words of every type. I could simply move all of the enums to one "Word" class, and have an attribute representing whether it is a particular type, but I would much rather keep the logical groups separate. – Timothy Egenton Dec 09 '21 at 20:27
  • Your question and comment is confusing. Perhaps you should describe your overall goal. – Basil Bourque Dec 09 '21 at 20:32
  • The overall goal is to convert from an input string to a Word enum value. This could be done with either directly checking each enum with valueOf(), or by checking against a dictionary set like I intended. Either way, I have to check against each of the separate enum classes, and I'd prefer to do it iteratively. – Timothy Egenton Dec 09 '21 at 20:37
  • You are saying that you want something like a dictionary? I think a map could be a better solution compared to iterating over each entry. – magicmn Dec 09 '21 at 23:13
  • 1
    Small suggestion: Instead of using `Arrays.asList(Article.values())`, use `EnumSet.allOf(Article.class)`. – Johannes Kuhn Dec 10 '21 at 06:33
  • 1
    If you want to look up a `Word` by string, just build a `Map`. It’s not clear why you claim you had “to check against each of the separate enum classes” when the code you’ve posted yourself proves that you don’t have to. – Holger Dec 10 '21 at 10:29

2 Answers2

2

Reflection only makes sense if you do not already know the enums (i.e. you have to discover the enums in a package).

If you already know the enums, then a variation of your code is reasonable.

For example:

public List<Word> allWords()
{
    List<Word> returnValue = new LinkedList<>();
    returnValue.addAll(Arrays.asList(Article.values()));
    returnValue.addAll(Arrays.asList(Conjunction.values()));
    returnValue.addAll(Arrays.asList(Verb.values()));
    // And so on...
    return returnValue;
}

I suggest a List. because the Set will remove duplicates by name.

Edit: My List suggestion now seems unnecessary.

Edit2: Per comment, set is not as bad as I want to believe it. Still, you are using the collection as a "list of junk", I suggest List is the better choice.

DwB
  • 37,124
  • 11
  • 56
  • 82
  • That's fair, I was just hoping for a simpler way to iterate over known class methods. – Timothy Egenton Dec 09 '21 at 21:21
  • 3
    A `Set` rejects duplicates by equality, not “by name”. All enum constants have an equality defined by their distinct identity, regardless of their name. – Holger Dec 10 '21 at 10:25
1

You can iterate through the values using Stream API or plain for-loop

allWords()
   .stream()
   .forEach(System.out::println);
// or
Stream.of(Article.values())
       .map(Article::text) // .text is a method from your interface Word
       .forEach(System.out::println);

but honestly, you are trying to do something strange with these enums.

What is your task? Why you are trying to solve it via enums at all?

lazylead
  • 1,453
  • 1
  • 14
  • 26