web-dev-qa-db-fra.com

Dans Java 8, comment transformer une carte <K, V> en une autre carte <K, V> à l'aide d'un lambda?

Je viens de commencer à regarder Java 8 et à essayer lambdas, je pensais essayer de réécrire une chose très simple que j'ai écrite récemment. Je dois transformer une carte chaîne en colonne en une autre carte en colonne où la colonne de la nouvelle carte est une copie défensive de la colonne de la première carte. La colonne a un constructeur de copie. Le plus proche que j'ai jusqu'à présent est:

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

mais je suis sûr qu'il doit y avoir une meilleure façon de le faire et je vous serais reconnaissant de quelques conseils.

122
annesadleir

Vous pouvez utiliser un Collector :

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}

Vous pouvez utiliser la méthode forEach pour faire ce que vous voulez.

Ce que tu fais là est:

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

Ce que nous pouvons simplifier en lambda:

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

Et comme nous appelons simplement une méthode existante, nous pouvons utiliser référence de la méthode , ce qui nous donne:

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

Le moyen le plus rapide sans réinsérer toutes les entrées dans la nouvelle carte ce ne sera pas le cas, car HashMap.clone exécute également le réhachage en interne.

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

Keep it Simple et utilisez 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

Voici une autre façon de vous donner accès à la clé et à la valeur en même temps, au cas où vous auriez à effectuer une transformation.

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

Si vous utilisez Guava (v11 minimum) dans votre projet, vous pouvez utiliser Maps :: transformValues .

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

Si vous ne craignez pas d'utiliser des bibliothèques tierces, my cyclops-react lib possède des extensions pour tous les types JDK Collection , y compris Map . Vous pouvez directement utiliser les méthodes map ou bimap pour transformer votre map. Un MapX peut être construit à partir d'une carte existante, par exemple.

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

Si vous souhaitez également changer la clé, vous pouvez écrire

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

bimap peut être utilisé pour transformer les clés et les valeurs en même temps.

Au fur et à mesure que MapX s'étend, la carte générée peut également être définie comme suit:

  Map<String, Column> y
1
John McClean