Comment dois-je écrire lorsque je veux convertir des valeurs de Map () en une autre classe à la fois?
Expliquons avec un exemple qui convertit Map <String, String>
en Map <String, Integer>
.
public Map<String, Integer> strToInt(final Map<String, String> map) {
final Map<String, Integer> ret = new HashMap<>();
for (final Map.Entry<String, String> entry : map.entrySet()) {
ret.put(entry.getKey(), Integer.valueOf(entry.getValue()));
}
return ret;
}
Pour le moment, il a été écrit en Java 7. Il y a beaucoup de code redondant et non essentiel.
public Map<String, Integer> strToInt(final Map<String, String> map) {
return map.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> Integer.valueOf(e.getValue())));
}
C'est plus court que le plan 1, mais c'est quand même un peu long.
public Map<String, Integer> strToInt(final Map<String, String> map) {
return Maps.transformValues(map, new Function<String, Integer>() {
@Override
public Integer apply(String input) {
return Integer.valueOf(input);
}
});
}
cette? Est-ce plus long que le plan 2? Non, vous pouvez utiliser Expression Lambda car la méthode abstraite est une interface fonctionnelle.
public Map<String, Integer> strToInt(final Map<String, String> map) {
return Maps.transformValues(map, v -> Integer.valueOf(v));
}
Vous pouvez également utiliser Reportez-vous à la méthode, afin de la raccourcir un peu.
public Map<String, Integer> strToInt(final Map<String, String> map) {
return Maps.transformValues(map, Integer::valueOf);
}
public Map<String, Integer> strToInt(final Map<String, String> map) {
return ImmutableMap.copyOf(Maps.transformValues(map, Integer::valueOf));
}
Proposition 3 avec ImmutableMap :: copyOf Enveloppé. L'explication sera décrite plus loin.
Maintenant, testons si cela fonctionne correctement.
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
interface MapValuesTransformer {
Map<String, Integer> strToInt(final Map<String, String> map);
/**
*Proposition 1:Utiliser pour la déclaration
*/
static class ForImpl implements MapValuesTransformer {
@Override
public Map<String, Integer> strToInt(final Map<String, String> map) {
final Map<String, Integer> ret = new HashMap<>();
for (final Map.Entry<String, String> entry : map.entrySet()) {
ret.put(entry.getKey(), Integer.valueOf(entry.getValue()));
}
return ret;
}
}
/**
*Proposition 2:Utiliser l'API Java 8 Stream
*/
static class StreamImpl implements MapValuesTransformer {
@Override
public Map<String, Integer> strToInt(final Map<String, String> map) {
return map.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> Integer.valueOf(e.getValue())));
}
}
/**
*Proposition 3:Cartes de goyave::Utiliser transformValues
*/
static class TranformValuesImpl implements MapValuesTransformer {
@Override
public Map<String, Integer> strToInt(final Map<String, String> map) {
return Maps.transformValues(map, Integer::valueOf);
}
}
/**
*Proposition 4:Cartes de goyave::Une autre solution utilisant transformValues
*/
static class CopyOfTranformValuesImpl implements MapValuesTransformer {
@Override
public Map<String, Integer> strToInt(final Map<String, String> map) {
return ImmutableMap.copyOf(Maps.transformValues(map, Integer::valueOf));
}
}
}
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class MapValuesTramsformerTest {
private final MapValuesTransformer transformer;
public MapValuesTramsformerTest(MapValuesTransformer transformer) {
this.transformer = transformer;
}
@Parameters(name = "{0}")
public static Iterable<MapValuesTransformer> testClasses() {
return Arrays.asList(
new MapValuesTransformer.ForImpl(),
new MapValuesTransformer.StreamImpl(),
new MapValuesTransformer.TranformValuesImpl(),
new MapValuesTransformer.CopyOfTranformValuesImpl()
);
}
//Écrivez divers tests ici
}
@Test
public void La valeur est-elle convertie?() {
Map<String, String> source = new HashMap<>();
source.put("one", "1");
source.put("zero", "0");
source.put("min", "-2147483648");
Map<String, Integer> expected = new HashMap<>();
expected.put("one", 1);
expected.put("zero", 0);
expected.put("min", Integer.MIN_VALUE);
// [Proposition 1: ForImpl] Passed
// [Proposition 2: StreamImpl] Passed
// [Proposition 3: TranformValuesImpl] Passed
// [Proposition 4: CopyOfTranformValuesImpl] Passed
assertThat(transformer.strToInt(source), is(expected));
}
Je l'ai passé en toute sécurité.
@Test
public void L'ordre est-il maintenu?() {
Map<String, String> source = new LinkedHashMap<>();
source.put("one", "1");
source.put("zero", "0");
source.put("min", "-2147483648");
Map<String, Integer> transformed = transformer.strToInt(source);
// [Proposition 1: ForImpl] Expected: is "[one, zero, min]" but: was "[zero, min, one]"
// [Proposition 2: StreamImpl] Expected: is "[one, zero, min]" but: was "[zero, min, one]"
// [Proposition 3: TranformValuesImpl] Passed
// [Proposition 4: CopyOfTranformValuesImpl] Passed
assertThat(transformed.keySet().toString(), is(source.keySet().toString()));
}
(Bien que ce soit un test approximatif pour suivre le résultat) Les plans 1 et 2 ont échoué.
Dans la mise en œuvre de Plan 1 et Plan 2, il devient HashMap, donc LinkedHashMap et [TreeMap](https://docs.oracle.com/javase/jp/8/ Si vous passez docs / api / java / util / TreeMap.html), la garantie de la commande est perdue.
@Test(expected = UnsupportedOperationException.class)
public void Immuable Est-ce immuable?() {
Map<String, String> source = new HashMap<>();
source.put("one", "1");
Map<String, Integer> expected = new HashMap<>();
expected.put("one", 1);
Map<String, Integer> transformed = transformer.strToInt(source);
// [Proposition 1: ForImpl] Failed
// [Proposition 2: StreamImpl] Failed
// [Proposition 3: TranformValuesImpl] Passed
// [Proposition 4: CopyOfTranformValuesImpl] Passed
transformed.put("two", 2);
}
Dans le cas du plan 3 et du plan 4, lorsque la méthode put de la carte convertie est appelée, [UnsupportedOperationException](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/UnsupportedOperationException] .html) est lancé.
Les propositions 1 et 2 étaient mutables et les propositions 3 et 4 étaient immuables.
@Test
La carte publique vide est-elle copiée?() {
Map<String, String> source = new HashMap<>();
source.put("one", "1");
Map<String, Integer> expected = new HashMap<>();
expected.put("one", 1);
Map<String, Integer> transformed = transformer.strToInt(source);
source.put("two", "2");
// [Proposition 1: ForImpl] Passed
// [Proposition 2: StreamImpl] Passed
// [Proposition 3: TransformValuesImpl]: Expected: is <{one=1}> but: was <{one=1, two=2}>
// [Proposition 4: CopyOfTranformValuesImpl] Passed
assertThat(transformed, is(expected));
}
Uniquement lors de la mise en œuvre du plan 3, les modifications apportées à la carte source de conversion après la conversion ont été reflétées dans la carte de destination de la conversion.
Il s'agit de [JavaDoc for Maps :: transformValues](https://guava.dev/releases/snapshot-jre/api/docs/com/google/common/collect/Maps.html#transformValues-java.util.Map- Comme décrit dans com.google.common.base.Function-), cette méthode "renvoie une vue de la carte".
Par conséquent, si vous souhaitez une copie (vous ne souhaitez pas refléter les modifications apportées à la carte source de conversion dans la destination de la conversion), ImmutableMap :: copyOf comme indiqué dans la proposition 4. Vous devez envelopper avec -jre / api / docs / com / google / common / collect / ImmutableMap.html # copyOf-java.util.Map-).
Tester la perspective | Proposition 1 | Proposition 2 | Proposition 3 | Proposition 4 |
---|---|---|---|---|
La valeur est-elle convertie? | Yes | Yes | Yes | Yes |
L'ordre est-il maintenu? | No | No | Yes | Yes |
Immutable(Immuable)Ou | No | No | Yes | Yes |
La carte est-elle copiée? | Yes | Yes | No | Yes |
Si vous connaissez les Avantages de l'immuabilité, la méthode de mise en œuvre de Plan 3 ou Plan 4 peut être meilleure. ?? Il paraît que.
Recommended Posts