从单例中展平流可选

时间:2017-02-14 11:41:01

标签: java lambda

此问题与mapflatMap中同时存在的Java 8 StreamOptional有关。值得注意的是,C#有一个名为SelectMany的类似构造。

我有learned about这两种方法,特别是在Stream中你可以使用flatMap从{{1}获得Collection<T>这就是我想要的。

在我的例子中,我有一个嵌套的类结构(来自我无法控制的DTD),我想在其中计算一个值的总和。我不会为了懒惰而编写类名。

Collection<Collection<T>>

给定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; } 类的Optional个实例我想DatiTelematico

我能做的最好的事情是使用嵌套的lambdas和普通的sum (importo) from telematico join adempimento join datiNegozio join negozio join tassazione方法

map

我试着开始写像

这样的东西

optionalTelematico.map(DatiTelematico :: getAdempimento)       .MAP(Adempimento :: getDatiNegozio)       .MAP(1→l.stream()flatMap(正&GT; n.getNegozio()流()flatMap(S-&GT;。s.getTassazione()流()flatMap(Tassazione :: getImporto))).... TBD

但后来我遇到编译错误

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));

如何巧妙地Method binding must be directly contained in a class (OTJLD A.3.1). (单身)切换到要求总和的Optional<T>? 我要求这样可以增加我对Java lambdas的了解。

3 个答案:

答案 0 :(得分:3)

OptionalStream实际上只代表一条数据 - 如果是可选的,那条数据可能不存在或存在,如果是流,则可能还有其他部分之前或之后的数据,但在当前时刻我们只有这件作品。

现在,

map方法本质上是OptionalStream的一种类型转换:映射采用函数I -> R,应用哪一个可以进行转换{{1} }(或Optional<I> -> Optional<R>)。

Stream<I> -> Stream<R>方法是一种可以改变的方法:

  • 将可选值转换为另一个可选值(可能为空)。这意味着函数类型flatMap
  • 流中的每个项转换为另一个流(其中包含0..n个元素)。这意味着函数类型I -> Optional<R>。请注意,对于流,此操作可以更改流中包含的元素数(但不会改变有效一次处理一个流元素的事实)。

在您的特定情况下,通过将转换设为可选,您最多可以直接获得I -> Stream<R>

Optional<List<DatiNegozio>>

Optional<List<DatiNegozio>> optDatiNegozio = optionalDatiTelematico .map(DatiTelematico::getAdempimento) // Optional<Adempimento> .map(Adempimento::getDatiNegozio); 您都可以通过List<DatiNegozio>轻松转换为Optional<BigDecimal>求和和访问元素:

Stream

如您所见,第二个代码段允许您将static Optional<BigDecimal> sumImporto(List<DatiNegozio> datiNegozio) { return datiNegozio.stream() // Stream<DatiNegozio> .map(DatiNegozio::getNegozio) // Stream<List<Negozio>> // unroll stream of collections into a stream of collection elements .flatMap(List::stream) // Stream<Negozio> .map(Negozio::getTassazione) // Stream<List<Tassazione>> // again, unroll stream of collections into a stream of collection elements .flatMap(List::stream) .map(Tassazione::getImporto) // Stream<BigDecimal> // last thing we need to do is just reduce .reduce(BigDecimal::add); } 转换为List<DatiNegozio>。在此之后,您有两种选择(风格选择):

  1. Optional<BigDecimal>的变体产生reduce而不是BigDecimal

    Optional<BigDecimal> //它产生具体的类型而不是可选的,因为即使在流中没有元素的情况下,我们至少可以返回我们开始的值 - ZERO

  2. 您可以使用第二个代码段生成可在.reduce(BigDecimal.ZERO, BigDecimal::add);中使用的函数 - 可选:

    flatMap

答案 1 :(得分:1)

您可以使用import tweepy # Consumer keys and access tokens, used for OAuth consumer_key = '' consumer_secret = '' access_token = '' access_token_secret = '' # OAuth process, using the keys and tokens auth = tweepy.OAuthHandler(consumer_key, consumer_secret) auth.set_access_token(access_token, access_token_secret) # Creation of the actual interface, using authentication api = tweepy.API(auth) for status in tweepy.Cursor(api.user_timeline, screen_name='@realDonaldTrump', tweet_mode="extended").items(): print(status.full_text) 方法将Collection.stream()转换为Collection并在Stream中使用它。因此flatMap的组合会为.map(d -> d.getList()).flatMap(Collection::stream)的所有内部列表返回流。

在您的情况下,它看起来像:

Stream<D>

答案 2 :(得分:0)

让我们说

Optional<DatiNegozio> abc = optionalTelematico.map(DatiTelematico::getAdempimento)
  .map(Adempimento::getDatiNegozio)

现在说abc.map(xyz)时。 xyz必须是将DatiNegozio的实例作为唯一参数的函数。在您的情况下,xyz是一个lambda,它接受一个参数l,其类型应为DatiNegozio。您现在正在执行l.stream(),这会导致编译错误beacsue stream()lDatiNegozio的实例)中不存在。