Partage
  • Partager sur Facebook
  • Partager sur Twitter

Comparer deux HashMap

    17 mai 2021 à 14:19:14

    Bonjour,

    Pour le cadre d'un projet, je dois comparer 2 HashMap et stocker les différences.

    MAP1 <String, Objet>

    MAP2 <String, Objet>

    J'ai des gros flux à comparer, je me pose des questions au niveau de la complexité. Dans un premier temps je comptais faire ça :

     for (String cle: MAP1.keySet()){
          for (String cle2: MAP2.keySet()){
               if(cle.equals(cle2){
                  if(MAP1.equals(MAP2)
                    return true
                  else
                     return false
                }    
           }
    }


    Je prend la 1ere clé de MAP1, je la cherche dans MAP2 si elle y est, je compare le contenu de mes objets. 

    Est-ce le meilleur moyen de faire ça ?

    Merci d'avance

    • Partager sur Facebook
    • Partager sur Twitter
      17 mai 2021 à 15:48:58

      Différence à quelle niveau? de la map elle même ou des objets insérés?
      • Partager sur Facebook
      • Partager sur Twitter
        17 mai 2021 à 16:07:35

        Play50hz a écrit:

        Différence à quelle niveau? de la map elle même ou des objets insérés?

        Des différences dans les données de l'objet.

        J'ai un objet personne par exemple et je veux comparer le nom, le prenom, l'age etc...

        • Partager sur Facebook
        • Partager sur Twitter
          17 mai 2021 à 16:33:54

          Dans les 2 maps, l'objet potentiellement identique est sur la même clé?
          • Partager sur Facebook
          • Partager sur Twitter
            17 mai 2021 à 16:40:57

            Play50hz a écrit:

            Dans les 2 maps, l'objet potentiellement identique est sur la même clé?


            Oui je peux avoir ce type de map.

            MAP 1 = ID: 1 | Valeur prenom : thomas nom : dupont age : 14

                         ID: 2 | Valeur prenom : remi nom : mary  age : 15

            MAP 2 = ID: 1 | Valeur prenom : thomas nom : dupont age : 14

                         ID: 2 | Valeur prenom : remi nom : mary  age : 17

            Et je dois afficher MAP 2 ->  ID: 2 | Valeur prenom : remi nom : mary  age : 17

            • Partager sur Facebook
            • Partager sur Twitter
              17 mai 2021 à 17:19:06

              Si les clés sont identiques, tu sors le keyset, tu itères dessus en faisant un equals entre les objets de la map 1 et 2 associés à la clé courante.
              • Partager sur Facebook
              • Partager sur Twitter
                17 mai 2021 à 17:31:34

                JeuneCodeur a écrit:

                Bonjour,

                Pour le cadre d'un projet, je dois comparer 2 HashMap et stocker les différences.

                MAP1 <String, Objet>

                MAP2 <String, Objet>

                J'ai des gros flux à comparer, je me pose des questions au niveau de la complexité. Dans un premier temps je comptais faire ça :

                 for (String cle: MAP1.keySet()){
                      for (String cle2: MAP2.keySet()){
                           if(cle.equals(cle2){
                              if(MAP1.equals(MAP2)
                                return true
                              else
                                 return false
                            }    
                       }
                }


                Je prend la 1ere clé de MAP1, je la cherche dans MAP2 si elle y est, je compare le contenu de mes objets. 

                Est-ce le meilleur moyen de faire ça ?

                Merci d'avance


                Clairement, non, ce n'est pas le meilleur moyen !

                Quand on a une clé (prise dans MAP1), on ne fait pas une boucle pour la chercher dans MAP2.  On interroge MAP2, par exemple avec containsKey

                for (String cle: MAP1.keySet()){
                      if (MAP2.containsKey(cle)) {
                               ....
                      }
                }
                

                Le parcours d'une Map coûte cher (temps proportionnel au nombre d'éléments qu'elle contient), alors que containsKey donne un accès direct (en temps amorti moyen constant, excusez le pédantisme).

                Ensuite,  il faudrait mieux préciser à quoi ça sert, parce que je ne suis pas sur qu'un parcours par des boucles soit la bonne solution à tous les problèmes.

                Il y a plus simple : on récupère les clés d'une des maps, on enlève les clés qui ne sont pas dans l'autre, et voila. Il y a des opérations sur les collections, il faut en profiter.

                // copie de la collection des clés du premier
                var Set<String> cles = new HashSet<>(MAP1.keySet());
                
                // on ne conserve que les clés qui sont dans le second
                cles.retainAll(MAP2.keySet());
                
                // et voila
                

                clés contient les clés communes aux deux ensembles (l'intersection).


                Techniquement, ça va faire tomber la complexité de n1 x n2  à  n1.log(n1) + n2.log(n2) , en fonction des tailles n1 et n2 des maps.



                -
                Edité par michelbillaud 17 mai 2021 à 17:35:12

                • Partager sur Facebook
                • Partager sur Twitter
                  17 mai 2021 à 17:58:40

                  J'ai cru comprendre que les keyset des 2 maps étaient identiques et que les différences étaient uniquement au niveau des objets associés, ce n'est pas le cas?
                  • Partager sur Facebook
                  • Partager sur Twitter
                    17 mai 2021 à 18:07:12

                    Avec la phrase

                    > Je prend la 1ere clé de MAP1, je la cherche dans MAP2 si elle y est,


                    on peut inférer qu'elle risque de ne pas y être.


                    Mon interprétation, c'est qu'on cherche les différences entre des objets qui ont les mêmes clés dans les deux maps.

                    -
                    Edité par michelbillaud 17 mai 2021 à 18:08:42

                    • Partager sur Facebook
                    • Partager sur Twitter
                      17 mai 2021 à 18:28:51

                      Par contre par rapport à: 

                      Différence à quelle niveau? de la map elle même ou des objets insérés?

                      Des différences dans les données de l'objet.

                      J'ai un objet personne par exemple et je veux comparer le nom, le prenom, l'age etc...

                      C'est clair que c'est pas clair!

                      • Partager sur Facebook
                      • Partager sur Twitter
                        17 mai 2021 à 18:36:52

                        Et bien il a des clés qui permettent de chercher des personnes dans deux maps. On va supposer que ces clés servent à identifier les personnes. Les maps donnent des infos.

                        Et il veut voir quelles infos diffèrent d'une map à l'autre, entre les objets qui sont censés contenir à peu près les mêmes infos. Ce qui a changé.

                        -
                        Edité par michelbillaud 17 mai 2021 à 18:37:27

                        • Partager sur Facebook
                        • Partager sur Twitter
                          18 mai 2021 à 11:06:54

                          Bonjour ! 

                          michelbillaud a écrit:


                          Clairement, non, ce n'est pas le meilleur moyen !

                          Quand on a une clé (prise dans MAP1), on ne fait pas une boucle pour la chercher dans MAP2.  On interroge MAP2, par exemple avec containsKey

                          for (String cle: MAP1.keySet()){
                                if (MAP2.containsKey(cle)) {
                                         ....
                                }
                          }
                          

                          Le parcours d'une Map coûte cher (temps proportionnel au nombre d'éléments qu'elle contient), alors que containsKey donne un accès direct (en temps amorti moyen constant, excusez le pédantisme).

                          -
                          Edité par michelbillaud il y a environ 17 heures


                          Je pense que je vais avoir besoin de cette solution !

                          Play50hz a écrit:

                          J'ai cru comprendre que les keyset des 2 maps étaient identiques et que les différences étaient uniquement au niveau des objets associés, ce n'est pas le cas?


                          Effectivement, théoriquement je suis censé avoir le même nombre d'éléments dans mes 2 maps, et que les keyset des 2 maps sont identiques et que les différences sont uniquement sur l'objet associés.

                          Et mon but est d'afficher les keyset où il y a une différence au niveau des objets (Je ne sais pas si j'ai été clair)

                          -
                          Edité par LawJava01 18 mai 2021 à 11:08:13

                          • Partager sur Facebook
                          • Partager sur Twitter
                            18 mai 2021 à 11:25:06

                            Dans ce cas, n'ayant pas l'assurance que l'ordre naturel est préservé dans les collections values si tu fais un sort, le plus simple je pense est d'itérer sur les clé d'une des map, sortir les values des 2 maps, et les comparer.

                            Tu peux faire ça avec un stream, un filtre et un collect pour sortir facilement une liste de ce qui n'est pas equals 

                            • Partager sur Facebook
                            • Partager sur Twitter
                              18 mai 2021 à 11:44:58

                              Je n'ai jamais utilisé un Stream apparemment c'est une sorte de requête si j'ai bien compris.

                              Le stream remplace donc mon idée de départ c'est à dire : 

                              for (String cle: MAP1.keySet()){
                              if (MAP2.containsKey(cle)) {
                              ....
                              }
                              }

                              Et ensuite comparer l'objet et le stocker dans une liste que j'afficherai a la fin

                              • Partager sur Facebook
                              • Partager sur Twitter
                                18 mai 2021 à 13:43:06

                                Bon donc on est bien dans le cas ou les deux maps ont LE MEME ensemble de clés ?

                                Comme on a besoin de chaque clé  ET de l'objet qui va de la map1 pour comparer l'objet avec son copain de la map2, je ferais plutot un stream sur l' entrySet, pour avoir les deux d'un coup

                                var messages = 
                                  map.entrySet().stream()
                                   .map( entry -> traficoter(entry.key(), entry.value(), map2.get(entry.key()))   // produit des messages ?
                                   .collect(....);
                                



                                • Partager sur Facebook
                                • Partager sur Twitter
                                  18 mai 2021 à 13:53:13

                                  michelbillaud a écrit:

                                  Bon donc on est bien dans le cas ou les deux maps ont LE MEME ensemble de clés ?

                                  Comme on a besoin de chaque clé  ET de l'objet qui va de la map1 pour comparer l'objet avec son copain de la map2, je ferais plutot un stream sur l' entrySet, pour avoir les deux d'un coup

                                  var messages = 
                                    map.entrySet().stream()
                                     .map( entry -> traficoter(entry.key(), entry.value(), map2.get(entry.key()))   // produit des messages ?
                                     .collect(....);
                                  

                                  Oui c'est ça !

                                  Donc la solution la plus efficace c'est partir sur un stream et non pas sur mes boucles for !

                                  Je vais essayer de me renseigner sur les streams et faire des tests ! Merci à vous 

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    18 mai 2021 à 14:02:47

                                    > la solution la plus efficace

                                    ça dépend comment on mesure l'efficacité. Un forEach peut aussi faire l'affaire

                                    map1.entrySet()
                                       .forEach( (k,v) -> faireQuelqueCHoseAvec(k, v, map2.get(k));
                                    



                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    Comparer deux HashMap

                                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                    • Editeur
                                    • Markdown