3 votes

Java Streams : Faire f() pour N - 1 éléments et g() pour N. C'est-à-dire une fonction différente pour le dernier élément.

Existe-t-il un moyen d'appeler l'API de flux Java pour exécuter une fonction pour tous les éléments d'un flux de données, sauf les derniers. Iterable et en appeler un autre sur le dernier sans le diviser en deux appels distincts ?

Cela permettrait d'éviter deux passages sur le tableau, l'un pour le diviser en tableau de tête et en élément de queue, l'autre pour itérer ces deux éléments et appliquer une fonction.

Mon cas d'utilisation est d'appeler repo.save(entity) sur tous les éléments sauf le dernier et repo.saveAndFlush(entity) sur le dernier.

Supposons que j'ai un Iterable<FooEntity> items;

J'espère une solution du type items.stream().???.profit(!)


Mise à jour :

Voici ma classe mise à jour selon le commentaire de @jonsharpe :

public class FooWriter implements ItemWriter<FooEntityManifest> {
  private final FooRepository fooRepo;

  @PersistenceContext
  private EntityManager em;

  @Autowired
  public FooWriter(FooRepository fooRepo) {
      this.fooRepo = fooRepo;
  }

  @Override
  public void write(List<? extends FooEntityManifest> items) {
      items.forEach(fooEM -> {
          FooEntity foo = fooEM.getChangedObject();
          fooRepo.save(foo);
      });
      em.flush();
  }
}

Comme je l'ai mentionné dans les commentaires, je ne suis pas sûr que cela injecte le bon EntityManager Je préfère donc utiliser le dépôt uniquement. Mes préoccupations sont-elles valables ?

P.S. Je réalise que l'interface de ma collection est de List et non Iterable mais je me posais la question d'une manière générale.

2voto

Mureinik Points 61228

Vous pouvez utiliser reduce pour simuler un tel comportement. Par exemple :

list.stream()
    .reduce((a, b) -> {
                repo.save(a);
                return b;
            })
    .ifPresent(x -> repo.saveAndFlush(x)); 

Mais, pour être tout à fait honnête, c'est assez maladroit, et du point de vue de la maintenance, vous feriez mieux d'utiliser la suggestion de @ jonrsharpe dans les commentaires - "Dans cet exemple, pourquoi ne pas .save all of them then .flush after" ?

2voto

Holger Points 13789

La solution la plus simple consiste à traiter tous les éléments de la même manière, comme suit

items.forEach(fooEM -> fooRepo.save(fooEM.getChangedObject()));
em.flush();

Si vous souhaitez traiter le dernier élément de manière spéciale, l'API Stream n'est pas le bon outil pour ce travail. Il existe des solutions possibles, mais elles seront plus compliquées que l'utilisation d'une autre API.

Par exemple, en considérant que votre point de départ est une List :

if(!items.isEmpty()) {
    int last = items.size()-1;
    items.subList(0, last).forEach(fooEM -> fooRepo.save(fooEM.getChangedObject()));
    fooRepo.saveAndFlush(items.get(last).getChangedObject());
}

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