2 votes

Java 8 utilisant stream, flatMap et lambda

J'ai ce morceau de code et je veux retourner une liste de codes postaux :

List<String> postcodes = new ArrayList<>();
List<Entry> entries = x.getEntry(); //getEntry() returns a list of Entry class
for (Entry entry : entries) {
    if (entry != null) {
       Properties properties = entry.getContent().getProperties();
       postcodes.addAll(Arrays.asList(properties.getPostcodes().split(",")));
   }
} 
return postcodes;

Voici ma tentative d'utiliser la méthode stream() et les méthodes enchaînées suivantes :

...some other block of code
List<Entry> entries = x.getEntry.stream()
    .filter(entry -> recordEntry != null)
    .flatMap(entry -> {
        Properties properties = recordEntry.getContent().getProperties();
        postCodes.addAll(Arrays.asList(properties.getPostcodes().split(",")));
});

5voto

Aomine Points 42709

Vous avez plusieurs problèmes avec votre code, c'est-à-dire que

  1. postCodes.addAll est un effet secondaire et vous devez donc éviter de le faire, sinon, lorsque le code est exécuté en parallèle, vous recevrez n on-déterministe les résultats.
  2. flatMap s'attend à un flux, pas à un booléen ; ce qui est ce que votre code tente actuellement de passer à flatMap .
  3. flatMap dans ce cas, consomme une fonction qui consomme également une valeur et renvoie une valeur. Si vous avez décidé d'utiliser un bloc d'instructions lambda, vous devez inclure une instruction de retour dans le bloc d'instructions lambda en spécifiant la valeur à renvoyer. ce n'est pas le cas dans votre code.
  4. Les pipelines de flux sont dirigés par terminal qui sont des opérations qui transforment un flux en une non-stream et votre code actuel ne s'exécutera pas du tout car vous avez juste mis en place les ingrédients mais pas réellement a demandé un résultat de la rivière.
  5. le type de récepteur de votre requête doit être List<String> no List<Entry> car dans votre code actuel, l'appel à Arrays.asList(properties.getPostcodes().split(",")) renvoie un List<String> que vous ajoutez ensuite à un accumulateur avec l'appel addAll .
  6. merci à Holger de l'avoir signalé, vous échouez constamment à décider si la variable est nommée entry o recordEntry .

Cela dit, voici comment je réécrirais votre code :

List<String> entries = x.getEntry.stream()
        .filter(Objects::nonNull)
        .map(Entry::getContent)
        .map(Content::getProperties)
        .map(Properties::getPostcodes‌)
        .flatMap(Pattern.co‌mpile(",")::splitAsS‌tream)
        .collect(Collectors.toList());

et vous pouvez utiliser Collectors.toCollection pour spécifier une implémentation spécifique de la liste retournée si cela est jugé approprié.

éditer :

avec quelques bonnes suggestions de shmosel, nous pouvons en fait utiliser des références de méthodes à travers les pipelines de flux et donc permettre une meilleure intention du code et beaucoup plus facile à suivre.

ou vous pouvez poursuivre l'approche :

List<String> entries = x.getEntry.stream()
       .filter(e -> e != null)
       .flatMap(e -> Arrays.asList(
         e.getContent().getProperties().getPostcodes().split(",")).stream()
       )
       .collect(Collectors.toList());

si c'est plus confortable pour vous.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X