Wassim Makni
Wassim Makni

Reputation: 471

Grouping by a Map value in Java 8 using streams

I have a List of Map that i want to group it by the key nom using java streams.

[
      {
        "dateDebut": "2018-07-01T00:00:00.000+0000",
        "nom": "Julien Mannone",
        "etat": "Impayé"
      },
      {
        "dateDebut": "2018-08-01T00:00:00.000+0000",
        "nom": "Julien Mannone",
        "etat": "Impayé"
      },          
      {
        "dateDebut": "2018-10-01T00:00:00.000+0000",
        "nom": "Mathiew Matic",
        "etat": "payé"
      },           
      {
        "dateDebut": "2018-10-01T00:00:00.000+0000",
        "nom": "Ash Moon",
        "etat": "payé"
      }
    ]

so i want as a result something like this

{  
   "Julien Mannone":[  
      {  
         "dateDebut":"2018-07-01T00:00:00.000+0000",
         "etat":"Impayé"
      },
      {  
         "dateDebut":"2018-08-01T00:00:00.000+0000",
         "etat":"Impayé"
      }
   ],
   "Mathiew Matic":[  
      {  
         "dateDebut":"2018-10-01T00:00:00.000+0000",
         "etat":"payé"
      }
   ],
   "Ash Moon":[  
      {  
         "dateDebut":"2018-10-01T00:00:00.000+0000",
         "etat":"payé"
      }
   ]
}

As a beginner in using streams I have made some research I found some codes like that

Map<String, List<Map>> afterFormatting =
        beforeFormatting.stream()
                .flatMap(m -> m.entrySet().stream())
                .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));

but that doesn't do the job for me

Upvotes: 10

Views: 22685

Answers (3)

Ousmane D.
Ousmane D.

Reputation: 56413

Seems like you're simply looking for:

Map<String, List<Map<String, String>>> afterFormatting = 
            beforeFormatting.stream()
                            .collect(Collectors.groupingBy(map -> map.get("nom")));

or if you don't want each Map<String, String> in the result set to contain the "nom" entry then you can do as follows:

Map<String, List<Map<String, String>>> afterFormatting = 
     beforeFormatting.stream()
                     .collect(Collectors.groupingBy(map -> map.get("nom"), 
                           Collectors.mapping(map -> { 
                                Map<String, String> temp = new HashMap<>(map);
                                temp.remove("nom");
                               return temp;
                     }, Collectors.toList())));

Upvotes: 13

user987339
user987339

Reputation: 10707

You just need to map stream to change the format to needed, and then collect:

list.stream().map(it -> {
                Map<String, Map<String, String>> newMap = new HashMap<>();
                String nom = it.get("nom");
                it.remove("nom");
                newMap.put(nom, it);
                return newMap;
            }
    ).collect(Collectors.toList())

Testable code:

    Map<String, String> m = new HashMap<>();
    m.put("dateDebut", "2018-07-01T00:00:00.000+0000");
    m.put("nom", "Julien Mannone");
    m.put("etat", "Impayé");

    Map<String, String> m2 = new HashMap<>();
    m2.put("dateDebut", "2018-10-01T00:00:00.000+0000");
    m2.put("nom", "Mathiew Matic");
    m2.put("etat", "payé");

    Map<String, String> m3 = new HashMap<>();
    m3.put("dateDebut", "2018-07-01T00:00:00.000+0000");
    m3.put("nom", "Ash Moon");
    m3.put("etat", "payé");

    List<Map<String, String>> list = new ArrayList<>();
    list.add(m);
    list.add(m2);
    list.add(m3);

    List<Map<String, Map<String, String>>> res = list.stream().map(it -> {
                Map<String, Map<String, String>> newMap = new HashMap<>();
                String nom = it.get("nom");
                it.remove("nom");
                newMap.put(nom, it);
                return newMap;
            }
    ).collect(Collectors.toList());

    System.out.println(res);

Upvotes: 1

dehasi
dehasi

Reputation: 2773

If I understand you correct you have a maps like

{
        "dateDebut": "2018-07-01T00:00:00.000+0000",
        "nom": "Julien Mannone",
        "etat": "Impayé"
      },

but then, when you call

.flatMap(m -> m.entrySet().stream()) You get a stream of all entry sets for all maps. But actually, your maps are not maps itself. They are rather POJO objects.

I suggest creating a class like

class Value {
String dateDebut, String nom, Etring etat;
// constructor
}

then convert each map to this class:

beforeFormatting.stream()
.map(m-> new Value(m.get("dateDebut"), m.get("nom"),m.get("etat"))

So now, you have a stream<Value> and you can easily group by in by "nom"

.collect(groupingBy(Value::getNom)

Upvotes: 1

Related Questions