I’m trying to perform a map operation on each entry in a Map
object.
I need to take a prefix off the key and convert the value from one type to another. My code is taking configuration entries from a Map<String, String>
and converting to a Map<String, AttributeType>
(AttributeType
is just a class holding some information. Further explanation is not relevant for this question.)
The best I have been able to come up with using the Java 8 Streams is the following:
private Map<String, AttributeType> mapConfig(Map<String, String> input, String prefix) { int subLength = prefix.length(); return input.entrySet().stream().flatMap((Map.Entry<String, Object> e) -> { HashMap<String, AttributeType> r = new HashMap<>(); r.put(e.getKey().substring(subLength), AttributeType.GetByName(e.getValue())); return r.entrySet().stream(); }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); }
Being unable to construct an Map.Entry
due to it being an interface causes the creation of the single entry Map
instance and the use of flatMap()
, which seems ugly.
Is there a better alternative? It seems nicer to do this using a for loop:
private Map<String, AttributeType> mapConfig(Map<String, String> input, String prefix) { Map<String, AttributeType> result = new HashMap<>(); int subLength = prefix.length(); for(Map.Entry<String, String> entry : input.entrySet()) { result.put(entry.getKey().substring(subLength), AttributeType.GetByName( entry.getValue())); } return result; }
Should I avoid the Stream API for this? Or is there a nicer way I have missed?
Advertisement
Answer
Simply translating the “old for loop way” into streams:
private Map<String, String> mapConfig(Map<String, Integer> input, String prefix) { int subLength = prefix.length(); return input.entrySet().stream() .collect(Collectors.toMap( entry -> entry.getKey().substring(subLength), entry -> AttributeType.GetByName(entry.getValue()))); }