J'essaie d'effectuer une opération de carte sur chaque entrée d'un objet Map
.
Je dois enlever un préfixe de la clé et convertir la valeur d'un type à un autre. Mon code prend les entrées de configuration d'un Map<String, String>
et les convertit en Map<String, AttributeType>
(AttributeType
est simplement une classe contenant des informations. Les explications supplémentaires ne sont pas pertinentes pour cette question.)
Le meilleur que j'ai pu trouver avec Java 8 Streams est le suivant:
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));
}
L'impossibilité de construire un Map.Entry
en raison de son interface constitue la création de l'instance à entrée unique Map
et l'utilisation de flatMap()
, ce qui semble déplorable.
Y a-t-il une meilleure alternative? Il semble plus agréable de faire cela en utilisant une boucle for:
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;
}
Devrais-je éviter l'API Stream pour cela? Ou y a-t-il une meilleure façon que j'ai manquée?
Traduisez simplement "l'ancien mode de boucle" en flux:
private Map<String, String> mapConfig(Map<String, Integer> input, String prefix) {
return input.entrySet().stream()
.collect(Collectors.toMap(
entry -> entry.getKey().substring(subLength),
entry -> AttributeType.GetByName(entry.getValue())));
}
La question est peut-être un peu datée, mais vous pouvez simplement utiliser AbstractMap.SimpleEntry <> comme suit:
private Map<String, AttributeType> mapConfig(
Map<String, String> input, String prefix) {
int subLength = prefix.length();
return input.entrySet()
.stream()
.map(e -> new AbstractMap.SimpleEntry<>(
e.getKey().substring(subLength),
AttributeType.GetByName(e.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
tout autre objet de valeur semblable à une paire fonctionnerait aussi (c.-à-d. ApacheCommons Pair Tuple).
Veuillez intégrer la partie suivante de l’API des collecteurs:
<K, V> Collector<? super Map.Entry<K, V>, ?, Map<K, V>> toMap() {
return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue);
}
Voici une solution plus courte par AbacusUtil
Stream.of(input).toMap(e -> e.getKey().substring(subLength),
e -> AttributeType.GetByName(e.getValue()));