Usando um Coletor de um primitivo stream
-
21-12-2019 - |
Pergunta
Existe no Java 8 de alguma forma para usar Stream::coletar(Colecionador) no primitivo fluxos?
Normalmente um Stream<Integer>
como exemplo tem-se dois métodos para a coleta:
<R,A> R collect(Collector<? super T,A,R> collector)
<R> R collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)
No entanto IntStream
só tem um método para a coleta:
Agora como código de exemplo eu tenho o seguinte:
@Override
public void run() {
result = LongStream.range(1, maximum).boxed()
.collect(Collectors.toMap(i -> i, i -> (int)Iterators.longStream(new CollatzGenerator(i)).count()))
.entrySet().stream()
.max(Comparator.comparingLong(Map.Entry::getValue))
.get().getKey();
}
Como você pode ver eu primeiro caixa de os primitivos, a fim de ser capaz de usar um Collectors.
o método.
Existe alguma maneira eu posso usar primitivos e ainda tem o mesmo código com Collectors.toMap
?
Solução
Desde Map
é uma interface Genérica não há nenhuma maneira para criar um Map
sem boxe.No entanto, isso não faz sentido para coletar itens em um Map
quando tudo que você quer é criar um outro fluxo (com apenas dois valores envolto em uma Map.Entry
).Você pode simplesmente criar o Map.Entry
instâncias sem recolher os valores:
LongStream.range(1, maximum)
.mapToObj(i->new AbstractMap.SimpleEntry<>(i, Iterators.longStream(new CollatzGenerator(i)).count()))
.max(Comparator.comparingLong(Map.Entry::getValue))
.get().getKey();
Isso ainda faz auto-boxe, mas uma vez que você está neste ponto, você pode livrar-se do Map.Entry
também através da criação de um valor apropriado classe de titular por si mesmo:
static final class TwoLongs {
final long key, value;
TwoLongs(long k, long v) { key=k; value=v; }
public long getKey() { return key; }
public long getValue() { return value; }
}
Com esta classe de titular, você pode processar os seus dados sem o boxe long
s:
LongStream.range(1, maximum)
.mapToObj(i->new TwoLongs(i, Iterators.longStream(new CollatzGenerator(i)).count()))
.max(Comparator.comparingLong(TwoLongs::getValue))
.get().getKey();
Bem, ainda é algum tipo de boxe, mas a criação de um item (o TwoLongs
instância) o objeto, em vez de três (um Map.Entry
e dois Long
s).
Outras dicas
long result = LongStream.range(0, 9)
.mapToObj(i -> new long[]{i, i})
.max(Comparator.comparingLong(pair -> pair[1]))
.get()[0];