Reputation: 1265
I have this enum:
public enum FieldType
{
INTEGER
{
@Override
Set<Class<?>> getTypes()
{
return new HashSet<>(Arrays.asList(int.class, Integer.class));
}
},
LONG
{
@Override
Set<Class<?>> getTypes()
{
return new HashSet<>(Arrays.asList(long.class, Long.class));
}
};
// More types...
private static final Map<Class<?>, FieldType> _fieldTypes;
static
{
_fieldTypes = Stream.of(values()).
flatMap(ft -> ft.getTypes().stream()).
collect(toMap(t -> t,
t -> Stream.of(values()).
filter(ft -> ft.getTypes().contains(t)).
findAny().
get()
));
}
abstract Set<Class<?>> getTypes();
// More methods...
}
As you can see, I have a map inside this enum that maps types to field types. I managed to populate this map in the static block using streams. It works, but I think that maybe there's a better and concise way to do it. I can put the second parameter of the toMap method in a new method, but I think I'm just moving the complexity somewhere else.
Do you have a suggestion on how to achieve the same thing in a simple way?
Upvotes: 0
Views: 85
Reputation: 120848
How about a little bit simpler:
Map<Class<?>, FieldType> map = Arrays.stream(FieldType.values())
.flatMap(ft -> ft.getTypes().stream()
.map(cl -> new AbstractMap.SimpleEntry<>(cl, ft)))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Obviously you could wrap it into Collections.unmodifiableMap
Upvotes: 1
Reputation: 33845
You can box into Entry
's while flatmapping:
_fieldTypes = Stream.of(values())
.flatMap(ft -> ft.getTypes().stream() // for every Class<?> of a FieldType...
.map(cls -> new SimpleEntry<>(cls, ft))) // get Entry<Class<?>, FieldType>
.collect(toMap(Entry::getKey, Entry::getValue));
As bradimus suggested, you can also use collectingAndThen
and Collections.unmodifiableMap
to create an unmodifiable map from the result of toMap
:
.collect(collectingAndThen(toMap(Entry::getKey, Entry::getValue),
Collections::unmodifiableMap));
Upvotes: 3