2
votes

Convertir une boucle arraylist avec java 8 foreach

Besoin de convertir for loop (Java 6) en foreach (Java 8)

custFormAttrLiteList.forEach((customFormAttributeLite)->
                custNameAndType = new HashMap<Long,Long>();
                custNameAndType.put(customFormAttributeLite.getId(), customFormAttributeLite.getFieldType());

                customNameId.put(customFormAttributeLite.getName(), custNameAndType);
            );

J'essaye quelque chose comme ça .. Mais je ne sais pas comment faire ça

 List<CustomFormAttributeLite> custFormAttrLiteList = ArrayList ... ;
Map<String,Map<Long,Long>> customNameId = new HashMap<String, Map<Long,Long>>();
Map<Long,Long> custNameAndType = null;

for(CustomFormAttributeLite customFormAttributeLite:custFormAttrLiteList) {

    custNameAndType = new HashMap<Long,Long>();
    custNameAndType.put(customFormAttributeLite.getId(), customFormAttributeLite.getFieldType());

    customNameId.put(customFormAttributeLite.getName(), custNameAndType);
}


2 commentaires

Ce sont des lambdas avec lesquels vous travaillez, c'est ce que vous devriez rechercher, vous avez à peu près le droit pour chaque.


Doit utiliser groupingBy idéalement.


3 Réponses :


1
votes

Vous ne pouvez utiliser que les variables finales à l'intérieur de chaque expression lambda. Alors essayez comme ceci:

final Map<String,Map<Long,Long>> customNameId = new HashMap<String, Map<Long,Long>>();
custFormAttrLiteList.forEach((customFormAttributeLite)-> {
                Map<Long,Long> custNameAndType = new HashMap<Long,Long>();
                custNameAndType.put(customFormAttributeLite.getId(), customFormAttributeLite.getFieldType());

                customNameId.put(customFormAttributeLite.getName(), custNameAndType);
            });


2 commentaires

+1, j'ajouterais qu'il n'est pas nécessaire de les marquer explicitement comme final , juste qu'ils soient effectivement finaux, ce qui signifie que le lambda ne peut pas attribuer une nouvelle valeur à la variable.


Oui c'est bien maintenant



1
votes

Vous pouvez également utiliser Collectors # groupingBy à cette fin. Commencez par grouper par le champ de nom, puis groupez par id et type de champ.

{bar={125=126}, foo={124=125}}

Si les noms ne sont pas uniques, le résultat ne sera pas le même que vous attendez donc dans ce cas nous devons utiliser Collectors.toMap et utilisez la mergeFunction pour ne conserver que le deuxième non-unique entrée:

CustomFormAttributeLite c1 = new CustomFormAttributeLite("foo", 123L, 123L);
CustomFormAttributeLite c2 = new CustomFormAttributeLite("foo", 124L, 125L);
CustomFormAttributeLite c3 = new CustomFormAttributeLite("bar", 125L, 126L);
CustomFormAttributeLite c4 = new CustomFormAttributeLite("bar", 125L, 126L);

Pour tester, j'ai utilisé l'ensemble de données suivant, pour tester ces deux solutions:

Map<String,Map<Long,Long>> customNameIdNonUnique = custFormAttrLiteList.stream()
                    .collect(Collectors.toMap(CustomFormAttributeLite::getName, //key mapper function
                     (obj) -> {Map<Long,Long> map = new HashMap<>(); map.put(obj.getId(), obj.getFieldType()); return map;}, //value mapper function
                     (key1, key2)-> key2)); //retaining only the second entry 

Le la deuxième solution a donné le résultat:

List<CustomFormAttributeLite> custFormAttrLiteList = new ArrayList<>();

Map<String,Map<Long,Long>> customNameId = custFormAttrLiteList.stream()
                        .collect(Collectors.groupingBy(CustomFormAttributeLite::getName,
                         Collectors.toMap(CustomFormAttributeLite::getId, CustomFormAttributeLite::getFieldType)));


1 commentaires

Vous pouvez également utiliser obj -> Collections.singletonMap (obj.getId (), obj.getFieldType ()) comme fonction de mappage de valeurs.



0
votes

Je vous recommande vivement d'éviter la mutation de l'état d'une collection dans forEach . Collectez les données en utilisant plutôt .collect (...) .

Commencez par créer une méthode ( statique ou dynamique ) pour mapper un CustomFormAttributeLite à Map:

Map<String, Map<Long, Long>> customNameId = 
    custFormAttrLiteList.stream()                                                                         
                        .collect(toMap(CustomFormAttributeLite::getName,this::mapToNameAndType));

Ensuite, vous pouvez simplement collecter les données dans un nouveau Carte en utilisant Collectors.toMap():

Map<Long,Long> mapToNameAndType(CustomFormAttributeLite attribute){
    Map<Long, Long> map = new HashMap<>();
    map.put(attribute.getId(), attribute.getFieldType());
    return map;
}


1 commentaires

list.forEach ! = list.stream (). forEach , rien de mal à muter en utilisant le premier, ce que fait l'OP.