This question is related to the Java 8 map
and flatMap
that is present both in Stream
s and Optional
s. It is worth to note that C# has a similar construct named SelectMany
.
I have learned about the two methods, in particular that in Stream
s 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.