it-swarm.com.de

In Java 8 Wie transformiere ich eine Map <K, V> mit einem Lambda in eine andere Map <K, V>?

Ich habe gerade angefangen, mir Java 8 anzuschauen und Lambdas auszuprobieren. Ich dachte, ich würde versuchen, eine sehr einfache Sache, die ich kürzlich geschrieben habe, umzuschreiben. Ich muss eine Map of String to Column in Eine weitere Karte von String zu Spalte, bei der die Spalte in der neuen Karte eine defensive Kopie der Spalte in der ersten Karte ist. Die Spalte hat einen Kopierkonstruktor.

    Map<String, Column> newColumnMap= new HashMap<>();
    originalColumnMap.entrySet().stream().forEach(x -> newColumnMap.put(x.getKey(), new Column(x.getValue())));

aber ich bin sicher, es muss eine schönere Möglichkeit geben, und ich wäre dankbar für einige Ratschläge.

122
annesadleir

Sie könnten ein Collector verwenden:

import Java.util.*;
import Java.util.stream.Collectors;

public class Defensive {

  public static void main(String[] args) {
    Map<String, Column> original = new HashMap<>();
    original.put("foo", new Column());
    original.put("bar", new Column());

    Map<String, Column> copy = original.entrySet()
        .stream()
        .collect(Collectors.toMap(Map.Entry::getKey,
                                  e -> new Column(e.getValue())));

    System.out.println(original);
    System.out.println(copy);
  }

  static class Column {
    public Column() {}
    public Column(Column c) {}
  }
}
191
McDowell
Map<String, Integer> map = new HashMap<>();
map.put("test1", 1);
map.put("test2", 2);

Map<String, Integer> map2 = new HashMap<>();
map.forEach(map2::put);

System.out.println("map: " + map);
System.out.println("map2: " + map2);
// Output:
// map:  {test2=2, test1=1}
// map2: {test2=2, test1=1}

Sie können die forEach -Methode verwenden, um das zu tun, was Sie wollen.

Was Sie dort tun, ist:

map.forEach(new BiConsumer<String, Integer>() {
    @Override
    public void accept(String s, Integer integer) {
        map2.put(s, integer);     
    }
});

Was wir zu einem Lambda vereinfachen können:

map.forEach((s, integer) ->  map2.put(s, integer));

Und weil wir nur eine existierende Methode aufrufen, können wir eine Methodenreferenz verwenden, die uns ergibt:

map.forEach(map2::put);
22
Arrem

Der Weg ohne erneutes Einfügen aller Einträge in die neue Map sollte der schnellste sein es wird nicht, weil HashMap.clone führt auch intern eine Aufbereitung durch.

Map<String, Column> newColumnMap = originalColumnMap.clone();
newColumnMap.replaceAll((s, c) -> new Column(c));
12
leventov

Halte es einfach und benutze Java 8: -

 Map<String, AccountGroupMappingModel> mapAccountGroup=CustomerDAO.getAccountGroupMapping();
 Map<String, AccountGroupMappingModel> mapH2ToBydAccountGroups = 
              mapAccountGroup.entrySet().stream()
                         .collect(Collectors.toMap(e->e.getValue().getH2AccountGroup(),
                                                   e ->e.getValue())
                                  );
7
Anant Khurana

Hier ist eine andere Möglichkeit, mit der Sie gleichzeitig auf den Schlüssel und den Wert zugreifen können, falls Sie eine Art Transformation durchführen müssen.

Map<String, Integer> pointsByName = new HashMap<>();
Map<String, Integer> maxPointsByName = new HashMap<>();

Map<String, Double> gradesByName = pointsByName.entrySet().stream()
        .map(entry -> new AbstractMap.SimpleImmutableEntry<>(
                entry.getKey(), ((double) entry.getValue() /
                        maxPointsByName.get(entry.getKey())) * 100d))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
3
Lucas Ross

Wenn Sie in Ihrem Projekt Guava (mindestens Version 11) verwenden, können Sie Maps :: transformValues verwenden.

Map<String, Column> newColumnMap = Maps.transformValues(
  originalColumnMap,
  Column::new // equivalent to: x -> new Column(x) 
)
2
Andrea Bergonzo

Wenn es Ihnen nichts ausmacht, Bibliotheken von Drittanbietern zu verwenden, hat my cyclops-react lib Erweiterungen für alle JDK Collection -Typen, einschließlich Map . Sie können die Karten- oder Bimap-Methoden direkt verwenden, um Ihre Karte zu transformieren. Eine MapX kann aus einer vorhandenen Map erstellt werden, z.

  MapX<String, Column> y = MapX.fromMap(orgColumnMap)
                               .map(c->new Column(c.getValue());

Wenn Sie auch den Schlüssel ändern möchten, können Sie schreiben

  MapX<String, Column> y = MapX.fromMap(orgColumnMap)
                               .bimap(this::newKey,c->new Column(c.getValue());

mit bimap können die Schlüssel und Werte gleichzeitig transformiert werden.

Wenn MapX Map erweitert, kann die generierte Map auch als definiert werden

  Map<String, Column> y
1
John McClean