java - móviles - manual de programacion android pdf
Devolver elemento vacío de la operación de mapa de Java 8 (4)
Usando el flujo de Java 8, ¿cuál es la mejor manera de asignar una List<Integer>
cuando no tiene salida para el Entero de entrada?
Simplemente devuelve nulo? Pero ahora el tamaño de mi lista de salida será más pequeño que el tamaño de mi entrada ...
List<Integer> input = Arrays.asList(0,1,2,3);
List<Integer> output = input.stream()
.map(i -> {
Integer out = crazyFunction(i);
if(out == null || out.equals(0))
return null;
return Optional.of(out);
})
.collect(Collectors.toList());
No entiendo por qué tú (y todas las respuestas) lo hacen tan complicado. Tienes una operación de mapeo y una operación de filtrado. Así que la forma más sencilla es aplicar estas operaciones una tras otra. Y a menos que su método ya devuelva un Optional
, no hay necesidad de tratar con Optional
.
input.stream().map(i -> crazyFunction(i))
.filter(out -> out!=null && !out.equals(0))
.collect(Collectors.toList());
Se puede simplificar a
input.stream().map(context::crazyFunction)
.filter(out -> out!=null && !out.equals(0))
.collect(Collectors.toList());
Pero parece que tiene una pregunta más teórica sobre qué tipo de List
generar, una con marcadores de posición para valores ausentes o una con un tamaño diferente al de la lista de entrada.
La respuesta simple es: no generar una lista . Una List
no es un fin en sí misma, por lo que debe considerar para qué tipo de operación necesita esta lista (o su contenido) y aplicar la operación como la operación de terminal del flujo. Luego tiene su respuesta, ya que la operación determina si los valores ausentes deben ser filtrados o representados por un valor especial (y qué valor tiene que ser).
Podría ser una respuesta diferente para diferentes operaciones ...
Puede envolver la salida en un Optional que puede o no contener un valor no nulo.
Con una salida: return Optional.of(out);
Sin salida: return Optional.<Integer>empty();
Debe incluir una opción porque una matriz no puede contener ningún valor nulo .
List<Integer> input = Arrays.asList(0,1,2,3);
List<Option<Integer>> output = input.stream()
.map(i -> {
Integer out = crazyFunction(i);
if(out == null || out.equals(0))
return Optional.<Integer>empty();
return Optional.of(out);
})
.collect(Collectors.toList());
Esto asegurará que input.size() == output.size()
.
Más adelante puede excluir el opcional vacío usando:
List<Integer> outputClean = output.stream()
.filter(Optional::isPresent)
.map(i -> {
return i.get();
})
.collect(Collectors.toList());
Reemplace la llamada de map
con flatMap
. La operación de map
produce un valor de salida por valor de entrada, mientras que la operación flatMap
produce cualquier número de valores de salida por valor de entrada, incluido cero.
La forma más directa es probablemente reemplazar el cheque de esta manera:
List<Integer> output = input.stream()
.flatMap(i -> {
Integer out = crazyFunction(i);
if (out == null || out.equals(0))
return Stream.empty();
else
return Stream.of(out);
})
.collect(Collectors.toList());
Una refactorización adicional podría cambiar crazyFunction
para que devuelva un Optional
(probablemente OptionalInt
). Si lo llama desde el map
, el resultado es un Stream<OptionalInt>
. Luego, debe hacer un flatMap
esa secuencia para eliminar los opcionales vacíos:
List<Integer> output = input.stream()
.map(this::crazyFunctionReturningOptionalInt)
.flatMap(o -> o.isPresent() ? Stream.of(o.getAsInt()) : Stream.empty())
.collect(toList());
El resultado de flatMap
es un Stream<Integer>
que flatMap
los int
s, pero está bien ya que los enviará a una List
. Si no iba a encasillar los valores int
en una List
, podría convertir el Stream<OptionalInt>
a un IntStream
utilizando lo siguiente:
flatMapToInt(o -> o.isPresent() ? IntStream.of(o.getAsInt()) : IntStream.empty())
Para obtener más información sobre cómo tratar con flujos de opciones, vea esta pregunta y sus respuestas .
Variantes más simples de la respuesta de @Martin Magakian:
List<Integer> input = Arrays.asList(0,1,2,3);
List<Optional<Integer>> output =
input.stream()
.map(i -> crazyFunction(i)) // you can also use a method reference here
.map(Optional::ofNullable) // returns empty optional
// if original value is null
.map(optional -> optional.filter(out -> !out.equals(0))) // return empty optional
// if captured value is zero
.collect(Collectors.toList())
;
List<Integer> outputClean =
output.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList())
;