I agree mostly with @200_success' answer, though for simplicity and maintainability I do suggest you to use the following, which is only possible in Java 8. It functionally does the same as @200_success' answer.
The code with explanation below:
public enum ContentType {
TITLE("$$title$$", SubType.MAIL),
BODY("$$body$$", SubType.MAIL),
MESSAGE("$$message$$", SubType.MAIL),
EVENTS("$$events$$", SubType.DEFAULT);
private static final Map<SubType, Set<ContentType>> SETS_BY_SUBTYPE;
static {
SETS_BY_SUBTYPE = Arrays.stream(values())
.collect(Collectors.groupingBy(
contentType -> contentType.getSubType(),
Collectors.toSet()
));
}
private final String replaceWord;
private final SubType subType;
private ContentType(final String replaceWord, final SubType subType) {
this.replaceWord = replaceWord;
this.subType = subType;
}
public String getReplaceWord() {
return replaceWord;
}
private SubType getSubType() {
return subType;
}
public static Set<ContentType> values(final SubType subType) {
return SETS_BY_SUBTYPE.get(subType);
}
}
enum SubType {
MAIL,
DEFAULT;
}
To explain it more precisely, consider only the code that generates the mapping:
SETS_BY_SUBTYPE = Arrays.stream(values())
.collect(Collectors.groupingBy(
contentType -> contentType.getSubType(),
Collectors.toSet()
));
What it does is:
- Obtain a
ContentType[]
.
- Convert the array to a
Stream<ContentType>
, this is the starting point of functional programming.
- Collect the stream in a data structure, here we want to have a
Map<SubType, Set<ContentType>>
.
- The unoverloaded version of
Collectors.groupingBy
groups elements on a certain property, here it is contentType.getSubType()
. The caveat with the default version is that it returns a List<ContentType>
whereas we want a Set<ContentType>
.
- So we need to supply a
downstream
argument to the method, which in this case becomes a Collectors.toSet()
downstream collector.
Another name suggestion would be to change SubType.ELSE
to SubType.DEFAULT
, where default semantically means that it does not belong to something else.
Other small remarks are about the horizontal white space, please be consistent there:
- Your enum declarations were missing one between the arguments.
- In one method there was too much horizontal whitespace.
I personally value horizontal whitespace and consistent looking code quite a bit as it in my opinion indicates how seriously you are working with your code.
Since the answer of @chillworld included using an EnumMap
, which is argubly better, at least for improved performance, we can construct it with the following:
private static final EnumMap<SubType, Set<ContentType>> SETS_BY_SUBTYPE;
static {
SETS_BY_SUBTYPE = Arrays.stream(values())
.collect(Collectors.groupingBy(
ContentType::getSubType,
() -> new EnumMap<>(SubType.class),
Collectors.toSet()
));
}
Here we explicitely specify an EnumMap
over the general Map
interface and to obtain it we use the third parameter of Collectors.groupingBy
, which is one that takes a mapFactory
as argument, which means that you need to provide the map yourself here.
Another difference is that we here use a method reference, ContentType::getSubType
, over contentType -> contentType.getSubType()
for improved readability.