Usando un recopilador en una secuencia primitiva
-
21-12-2019 - |
Pregunta
¿Hay alguna forma de utilizar Java 8? Corriente::recopilar(Coleccionista) en corrientes primitivas?
Normalmente un Stream<Integer>
como ejemplo tiene dos métodos para recolectar:
<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)
Sin embargo IntStream
solo tiene un método para recolectar:
Ahora como código de ejemplo tengo el siguiente:
@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 puedes ver, primero encuadro las primitivas para poder usar un Collectors.
método.
¿Hay alguna manera de que pueda usar primitivos y seguir teniendo el mismo código? Collectors.toMap
?
Solución
Desde Map
es una interfaz genérica, no hay forma de crear una Map
sin boxeo.Sin embargo, no tiene sentido recolectar elementos en un Map
en absoluto cuando todo lo que desea es crear otra secuencia (con solo dos valores envueltos en un Map.Entry
).Puedes simplemente crear el Map.Entry
instancias sin recopilar los 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();
Esto todavía hace auto-boxing pero una vez que estés en este punto puedes deshacerte del Map.Entry
también creando una clase de titular de valor adecuada por usted mismo:
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; }
}
Con esta clase de titular podrás procesar tus datos sin encajonar el long
s:
LongStream.range(1, maximum)
.mapToObj(i->new TwoLongs(i, Iterators.longStream(new CollatzGenerator(i)).count()))
.max(Comparator.comparingLong(TwoLongs::getValue))
.get().getKey();
Bueno, sigue siendo una especie de boxeo, pero crear un elemento (el TwoLongs
instancia) objeto en lugar de tres (uno Map.Entry
y dos Long
s).
Otros consejos
long result = LongStream.range(0, 9)
.mapToObj(i -> new long[]{i, i})
.max(Comparator.comparingLong(pair -> pair[1]))
.get()[0];