IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Collection et Stream Java Discussion :

[stream] convert map of list to map


Sujet :

Collection et Stream Java

  1. #1
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut [stream] convert map of list to map
    Bonjour j'ai une map<String,List<String>> et je voudrais la convertir en map<String,String>
    mais je voudrais inverser les clefs.
    { a: [ A, B, C, D], b: [Z], c: [X, Y]} devient : { A: a, B: a, C: a, D: a, Z: b, X: c, Y: c}.

    j'ai trouvé comment faire pour inverser une map<String,String> en map<String,String> key => en value => key
    mais je n'ai pas trouvé comment faire ça avec une liste de valeur.

    du coup pour le moment j'utilise l'API stream pour parcourir la map avec un foreach dans le consumer je parcours la liste là aussi avec un foreach et avec un bon vieux newMap.add je crée ma map.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    original.entrySet()
      .stream()
      .forEach((entry) -> {
        entry.getValue().forEach((value) -> {
          nyMap.put(value, entry.getKey());
        });
      });

    je pense qu'il doit être possible de faire ça avec un collect toMap
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Map<String, String> copy = original.entrySet()
            .stream()
            .collect(Collectors.toMap(Map.Entry::getValue,Map.Entry::getKey));
    le pb c'est que je ne vois pas comment à la place du Map.Entry::getValue produire chaque valeur à la place de la liste.

    A+JYT

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Je vois déjà vite fait trois solutions (je réfléchirai à des solutions plus simple plus tard) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    Map<String, List<String>> map = new HashMap<>();
    		map.put("a", Arrays.asList("A", "B", "C", "D"));
    		map.put("b", Arrays.asList("Z"));
    		map.put("c", Arrays.asList("X", "Y"));
     
     
    		Map<String,String> res = map.entrySet().stream()
    				.collect(HashMap::new, 
    				(m, e) -> e.getValue().forEach(v -> m.put(v, e.getKey())),
    				Map::putAll);
     
    		System.out.println(res);
     
    		Map<String,String> res2 = map.entrySet().stream()
    				.flatMap(e-> e.getValue().stream().map(v-> new AbstractMap.SimpleEntry<String,String>(v,e.getKey())))
    				.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
     
    		System.out.println(res2);
     
                    Map<String,String> res3 = map.entrySet().stream()
    				.flatMap(e-> e.getValue().stream().collect(Collectors.toMap(v-> v, v-> e.getKey()))
    						.entrySet().stream())
    				.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
    		System.out.println(res3);
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Une solution par réduction aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Map<String,String> res4 = map.entrySet().stream().reduce(
    	            new HashMap<String,String>(), 
    	            (m, e) -> {
    	                e.getValue().forEach(v -> m.put(v, e.getKey()));
    	                return m;
    	            }, 
    	            (m1, m2) -> {
    	                m2.putAll(m1);
    	                return m2;
    	            }
    	        );
    		System.out.println(res4);
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  4. #4
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    merci

    je vais regarder tout ça et chercher à en comprendre les principes.

    A+JYT

  5. #5
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Encore une autre (une fusion des idées précédentes), peut-être la meilleure, parce que la plus simplement compréhensible (les étapes correspondent bien à ce qu'on ferait le plus naturellement, je pense) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Map<String,String> res5 = map.entrySet().stream()
    			 .map(e-> e.getValue().stream().collect(Collectors.toMap(v-> v, v-> e.getKey()))) // on inverse clef et liste de valeur pour fabriquer les maps inverses correspondant
    			 .flatMap(m-> m.entrySet().stream()) // on met à plat l'ensemble des nouvelles maps pour obtenir un flux de toutes les valeurs de toutes les listes, mappées vers leur clef correspondant
    			 .collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue)); // on refabrique la map résultat en associant clef et valeur naturellement
    System.out.println(res5);
    Bien sûr tout ceci ne fonctionne qui si les valeurs dans les listes sont bien distinctes, forcément, et si ce n'est pas la cas, on n'a aucune exception.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  6. #6
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    Merci

    il faut que je me penche sérieusement sur flatmap
    qui est la clef de cette problématique.

    A+JYT

  7. #7
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    J'ai dît d'ailleurs une bêtise : on n'a bien une exception en cas de valeurs non distinctes, sauf pour les première et quatrième solutions.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  8. #8
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Et la version avec un Collector custom, qui permet de gérer l'exception de valeurs non distinctes avec le message qu'on veut.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    public class XCollectors {
     
    	public static <K, V, E extends Map.Entry<K, ? extends Collection<V>>> Collector<E,Map<V,K>,Map<V,K>> reverseOfMapOfListCollector() {
    		return reverseOfMapOfListCollector(HashMap::new);
    	}
    	public static <K, V, E extends Map.Entry<K, ? extends Collection<V>>> Collector<E,Map<V,K>,Map<V,K>> reverseOfMapOfListCollector(Supplier<Map<V, K>> supplier) {
    		return new Collector<E,Map<V,K>,Map<V,K>>() {
     
    			@Override
    			public Supplier<Map<V, K>> supplier() {
    				return supplier;
    			}
     
    			@Override
    			public Function<Map<V, K>, Map<V, K>> finisher() {
    				return Function.identity();
    			}
     
    			@Override
    			public Set<Characteristics> characteristics() {
    				return EnumSet.of(Characteristics.UNORDERED);
    			}
     
    			@Override
    			public BiConsumer<Map<V, K>, E> accumulator() {
    				return (m2, e)-> {  
    					e.getValue()
    					  .stream()
    					  .peek(k-> {
    						  if (m2.containsKey(k)) {
    							  throw new IllegalStateException("Duplicate value "+k+" mapped to "+m2.get(k)+" and "+e.getKey());
    						  }
    					  })
    					  .forEach(v-> m2.put(v, e.getKey()));
    				};
    			} 
     
    			@Override
    			public BinaryOperator<Map<V, K>> combiner() {
    				return (m1, m2)-> { 
    					m2.putAll(m1);
    					return m2;
    				};
    			} 
     
    		};
    	}
     
    }
    et qui s'appelle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Map<String,String> res6 = map.entrySet().stream()
    				.collect(XCollectors.reverseOfMapOfListCollector());
    System.out.println("6 "+res6);
    Encore que pas facile de lui donner un nom...
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Convert Object to List of String
    Par UNIX107 dans le forum Langage
    Réponses: 2
    Dernier message: 15/04/2010, 13h35
  2. Convert String to List
    Par hibernatefun dans le forum Langage
    Réponses: 6
    Dernier message: 16/02/2010, 18h05
  3. Réponses: 3
    Dernier message: 02/02/2009, 19h13
  4. Problem de Map et de List
    Par Roming22 dans le forum C++
    Réponses: 5
    Dernier message: 29/05/2006, 11h29
  5. [MAP] comment récupérer la liste des clé ordonnées
    Par Alec6 dans le forum Collection et Stream
    Réponses: 7
    Dernier message: 21/07/2004, 16h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo