Wie soll ich schreiben, wenn ich Map-Werte () sofort in eine andere Klasse konvertieren möchte? Lassen Sie uns anhand eines Beispiels erklären, das "Map <String, String>" in "Map <String, Integer>" konvertiert.
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;
}
Vorerst wurde es auf Java 7 geschrieben. Es gibt viel Code, der redundant und nicht wesentlich ist.
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())));
}
Es ist kürzer als Plan 1, aber immer noch etwas lang.
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);
}
});
}
Das? Ist es länger als Plan 2? Nein, Sie können Lambda-Ausdruck verwenden, da die abstrakte Methode eine funktionale Schnittstelle ist.
public Map<String, Integer> strToInt(final Map<String, String> map) {
return Maps.transformValues(map, v -> Integer.valueOf(v));
}
Sie können auch Siehe Methode verwenden, um es etwas kürzer zu machen.
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));
}
Vorschlag 3 mit ImmutableMap :: copyOf Eingewickelt. Die Erklärung wird später beschrieben.
Testen wir nun, ob es richtig funktioniert.
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);
/**
*Vorschlag 1:Zur Aussage verwenden
*/
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;
}
}
/**
*Vorschlag 2:Verwenden Sie die Java 8 Stream-API
*/
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())));
}
}
/**
*Vorschlag 3:Guaven-Karten::Verwenden Sie transformValues
*/
static class TranformValuesImpl implements MapValuesTransformer {
@Override
public Map<String, Integer> strToInt(final Map<String, String> map) {
return Maps.transformValues(map, Integer::valueOf);
}
}
/**
*Vorschlag 4:Guaven-Karten::Eine andere Lösung mit 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()
);
}
//Schreiben Sie hier verschiedene Tests
}
@Test
public void Wird der Wert konvertiert?() {
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);
// [Vorschlag 1: ForImpl] Passed
// [Vorschlag 2: StreamImpl] Passed
// [Vorschlag 3: TranformValuesImpl] Passed
// [Vorschlag 4: CopyOfTranformValuesImpl] Passed
assertThat(transformer.strToInt(source), is(expected));
}
Ich habe es sicher bestanden.
@Test
public void Wird die Bestellung aufrechterhalten?() {
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);
// [Vorschlag 1: ForImpl] Expected: is "[one, zero, min]" but: was "[zero, min, one]"
// [Vorschlag 2: StreamImpl] Expected: is "[one, zero, min]" but: was "[zero, min, one]"
// [Vorschlag 3: TranformValuesImpl] Passed
// [Vorschlag 4: CopyOfTranformValuesImpl] Passed
assertThat(transformed.keySet().toString(), is(source.keySet().toString()));
}
(Obwohl es ein grober Test ist, das Ergebnis zu testen) Plan 1 und Plan 2 sind fehlgeschlagen.
Bei der Implementierung von Plan 1 und Plan 2 wird HashMap geändert, sodass LinkedHashMap und TreeMap Wenn Sie docs / api / java / util / TreeMap.html übergeben, geht die Garantie der Bestellung verloren.
@Test(expected = UnsupportedOperationException.class)
public void Unveränderlich Ist es unveränderlich?() {
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);
// [Vorschlag 1: ForImpl] Failed
// [Vorschlag 2: StreamImpl] Failed
// [Vorschlag 3: TranformValuesImpl] Passed
// [Vorschlag 4: CopyOfTranformValuesImpl] Passed
transformed.put("two", 2);
}
Im Fall von Plan 3 und Plan 4, wenn die Put-Methode der konvertierten Map aufgerufen wird, [UnsupportedOperationException](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/UnsupportedOperationException] .html) wird geworfen.
Die Vorschläge 1 und 2 waren veränderlich und die Vorschläge 3 und 4 waren unveränderlich.
@Test
Wird die öffentliche leere Karte kopiert?() {
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");
// [Vorschlag 1: ForImpl] Passed
// [Vorschlag 2: StreamImpl] Passed
// [Vorschlag 3: TransformValuesImpl]: Expected: is <{one=1}> but: was <{one=1, two=2}>
// [Vorschlag 4: CopyOfTranformValuesImpl] Passed
assertThat(transformed, is(expected));
}
Nur bei der Implementierung von Plan 3 wurden die nach der Konvertierung an der Conversion-Quellkarte vorgenommenen Änderungen in der Conversion-Zielkarte berücksichtigt.
Dies ist [JavaDoc für Maps :: transformValues](https://guava.dev/releases/snapshot-jre/api/docs/com/google/common/collect/Maps.html#transformValues-java.util.Map- Wie in com.google.common.base.Function-) beschrieben, gibt diese Methode "eine Ansicht der Karte zurück".
Wenn Sie daher eine Kopie wünschen (Sie möchten die Änderungen an der Conversion-Quellzuordnung im Conversion-Ziel nicht widerspiegeln), wählen Sie ImmutableMap :: copyOf, wie in Vorschlag 4 gezeigt. Sie müssen mit -jre / api / docs / com / google / common / collect / ImmutableMap.html # copyOf-java.util.Map-) umbrechen.
Testperspektive | Vorschlag 1 | Vorschlag 2 | Vorschlag 3 | Vorschlag 4 |
---|---|---|---|---|
Wird der Wert konvertiert? | Yes | Yes | Yes | Yes |
Wird die Bestellung beibehalten? | No | No | Yes | Yes |
Immutable(Unveränderlich)Oder | No | No | Yes | Yes |
Wird die Karte kopiert? | Yes | Yes | No | Yes |
Wenn Ihnen [Vorteile der Unveränderlichkeit] bekannt sind (https://www.ibm.com/developerworks/jp/java/library/j-jtp02183/index.html), ist die Implementierungsmethode von Plan 3 oder Plan 4 möglicherweise besser. ?? Es scheint, dass.
Recommended Posts