Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

270
Visualizações
Java collector teeing a list of inputs

I am trying to implement a simple collector, which takes a list of collectors and simultaneously collects values in slightly different ways from a stream.

It is quite similar to Collectors.teeing, but differs in that it

  1. Receives a list of collectors instead of just two
  2. Requires all collectors to produce a value of the same type

The type signature I want to have is

public static <T, R> Collector<T, ?, List<R>> list(
      final List<Collector<T, ?, R>> downstreamCollectors);

One way to create such a collector would be to recursively pair up teeing collectors, like so:

public static <T, R> Collector<T, ?, List<R>> list(
    final List<Collector<T, ?, R>> downstreamCollectors) {
  return listrec(
      Collectors.collectingAndThen(downstreamCollectors.get(0), List::of),
      downstreamCollectors.stream().skip(1).toList());
}

private static <T, R> Collector<T, ?, List<R>> listrec(
    final Collector<T, ?, List<R>> teedCollectors,
    final List<Collector<T, ?, R>> downstreamCollectors) {
  if (downstreamCollectors.size() == 0) {
    return teedCollectors;
  } else {
    return listrec(
        teeing(
            teedCollectors,
            downstreamCollectors.get(0),
            (l, s) -> Stream.concat(l.stream(), Stream.of(s)).toList()),
        downstreamCollectors.stream().skip(1).toList());
  }
}

Something feels a little "off" with this solution, so I am trying to create the collector myself, something like:

public static <T, R> Collector<T, ?, List<R>> list2(
    final List<Collector<T, ?, R>> downstreamCollectors) {
  return Collector.of(
      () -> downstreamCollectors.stream().map(c -> c.supplier().get()).toList(),
      (accumulators, t) ->
          IntStream.range(0, downstreamCollectors.size())
              .forEach(
                  i -> downstreamCollectors.get(i).accumulator().accept(accumulators.get(i), t)),
      (accumulator1, accumulator2) ->
          IntStream.range(0, downstreamCollectors.size())
              .mapToObj(
                  i ->
                      downstreamCollectors
                          .get(i)
                          .combiner()
                          .apply(accumulator1.get(i), accumulator2.get(i)))
              .toList(),
      accumulators ->
          IntStream.range(0, downstreamCollectors.size())
              .mapToObj(i -> downstreamCollectors.get(i).finisher().apply(accumulators.get(i)))
              .toList());
}

Because of the unbounded wildcard in the downstream collectors' accumulator type, this doesn't compile. Changing the type signature to

public static <T, A, R> Collector<? super T, ?, List<R>> list2(
    final List<Collector<? super T, A, R>> downstreamCollectors);

solves the problem, but unfortunately renders the method much less usable as the downstream collectors (like the built in collectors from java.util.stream.Collectors) typically would have a unbounded wildcard in the accumulator type.

Is there another way to implement this, keeping the wildcard in the method signature?

I am using OpenJDK 17.0.2.

over 4 years ago · Santiago Trujillo
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda