Tengo una lista opcional de una clase, es decir: Optional<List<MyEntity>> opListEntity
Necesitaba asignar todo MyEntity a MyEntityDto cuando Opcional está presente. En caso de que Optional esté vacío, devolveré un ArrayList vacío.
Enfoque 1 (no funcional):
Nota: myEntityMapper es un objeto de una clase de mapeador, que asigna MyEntity a MyEntityDto .
List<MyEntityDto> res; if (opListEntity.isPresent()) { res = opListEntity.get().stream() .map(myEntityMapper::entityToDto) .collect(Collectors.toList()); } else { res = new ArrayList<>(); }Este enfoque está bien, pero IntelliJ sugiere convertirlo en una expresión de estilo funcional. Dejo que IntelliJ haga la conversión y esto es lo que obtengo:
Enfoque 2 (expresión de función):
List<MyEntityDto> res = opListEntity.map(myEntities -> myEntities.stream() .map(myEntityMapper::entityToDto) .collect(Collectors.toList())) .orElseGet(ArrayList::new);Lo que no entiendo es, en el enfoque 2 @ línea 1, ¿por qué hay un mapa?
Déjame explicarte un poco más. Ver el 3er Enfoque:
Enfoque 3:
List<CustomerAddressEntity> myEntities = opListEntity .orElseGet(ArrayList::new); List<MyEntityDto> res = myEntities.stream() .map(myEntityMapper::entityToDto) .collect(Collectors.toList());El enfoque 3 funciona bien, pero si trato de convertir el enfoque 3 al enfoque 4, no funciona.
Enfoque 4:
List<MyEntityDto> res = opListEntity.stream() .map(myEntityMapper::entityToDto) .collect(Collectors.toList())) .orElseGet(ArrayList::new); ¿Por qué el enfoque 4 no funciona pero el enfoque 2 sí?
¿Qué hace el mapa adicional en el enfoque 2 @ línea 1?
Creo que se vuelve obvio si sangra un poco más el código para que sea un poco más fácil de detectar:
List<MyEntityDto> res = opListEntity // Optional<List<MyEntity>> .map( myEntities -> myEntities.stream() // Stream<MyEntity> .map(myEntityMapper::entityToDto) // Stream<MyEntityDto> .collect(Collectors.toList()) // List<MyEntityDto> ) .orElseGet(ArrayList::new); // List<MyEntityDto> Es decir, Optional (si está presente) se asigna al resultado de transformar la lista contenida en una secuencia, asignar los elementos y crear una colección, o (si está vacío) a una nueva lista vacía.
En su cuarto enfoque, opListEntity es de tipo Optional<List<MyEntity>> . Ahora depende de la versión de JDK que estés usando. En JDK8 Optional no tiene método stream() .
List<MyEntityDto> res = opListEntity.stream() // there is no such method in JDK8 ... Dado que JDK9 hay un método stream() pero, por supuesto, devolverá Stream<List<MyEntity>> ya que este es el tipo de Optional . Pero para que la asignación funcione, necesitaría Stream<MyEntity> . Para obtener esto, puede mapear la secuencia devuelta utilizando el método flatMap :
List<MyEntityDto> res = opListEntity.stream() // Stream<List<MyEntity>> .flatMap(List::stream) // Stream<MyEntity> .map(myEntityMapper::entityToDto) ...