This question is related to the Java 8 map and flatMap that is present both in Streams and Optionals. It is worth to note that C# has a similar construct named SelectMany.
I have learned about the two methods, in particular that in Streams you can use flatMap to get a Collection<T> from a Collection<Collection<T>> which is what I want.
In my example I have a nested class structure (from a DTD I have no control over) in which I want to compute a sum of values. I will not redact the class names for laziness.
class DatiTelematico {
private Adempimento adempimento;
}
class Adempimento {
private List<DatiNegozio> datiNegozio;
}
class DatiNegozio {
private List<Negozio> negozio;
}
class Negozio {
private List<Tassazione> tassazione;
}
class Tassazione {
private BigDecimal importo;
}
Given an Optional instance of a DatiTelematico class I would like to sum (importo) from telematico join adempimento join datiNegozio join negozio join tassazione.
The best I could do was to use nested lambdas and plain map method
optionalTelematico.map(DatiTelematico::getAdempimento)
.map(Adempimento::getDatiNegozio)
.map(l -> l.stream().map(DatiNegozio::getNegozio)
.map(n -> n.stream()
.map(Negozio::getTassazione)
.map(t -> t.stream()
.map(Tassazione::getImporto)
.reduce(BigDecimal.ZERO,
BigDecimal::add))
.reduce(BigDecimal.ZERO, BigDecimal::add))
.reduce(BigDecimal.ZERO, BigDecimal::add))
.orElse(BigDecimal.ZERO));
I have tried to start writing something like
optionalTelematico.map(DatiTelematico::getAdempimento) .map(Adempimento::getDatiNegozio) .map(l->l.stream().flatMap(n->n.getNegozio().stream().flatMap(s->s.getTassazione().stream().flatMap(Tassazione::getImporto)))....TBD
But then I get a compiler error
Method binding must be directly contained in a class (OTJLD A.3.1).
How do I smartly switch from an Optional<T> (singleton) to a Collection<U> that is to be summed over?
I am asking this to increase my knowledge of Java lambdas.