RxJava:使用反应式方法处理命令式任务

RxJava:使用反应式方法处理命令式任务,java,reactive-programming,rx-java2,Java,Reactive Programming,Rx Java2,下面是以下类结构: class SomeEntity { private Collection<SomeData> dataCollection; private BigDecimal price; ... } class SomeData { private Long personId; ... } class Person { private Collection<AddressLink> addressesLink

下面是以下类结构:

class SomeEntity {
    private Collection<SomeData> dataCollection;
    private BigDecimal price;
    ...
}

class SomeData {
    private Long personId;
    ...
}

class Person {
    private Collection<AddressLink> addressesLinks; //AddressLink is a representation of the link to the address entity
    ...
} 
ShipmentData创建方法可以如下所示:

private static List<ShipmentData> createShipmentData(SomeEntity entity, Map<Person, List<Collection<AddressLink>>> personToAddressesLinkMap) {
    List<ShipmentData> result = new ArrayList<>();

    ...

    ShipmentData data = new ShipmentData();
    data.setTargetId(...); // Person.addressLink
    data.setRecepientId(...); // SomeEntity.someData.personId
    data.setPrice(...); // SomeEntity.price
    data.setSourceId(...); //SomeEntity.someData.id
    data.setCreationDate(LocalDateTime.now());

    ...

    return result;
}
这个反应流在访问方面将数据缩小到
地址
对象。我既不能访问
person
也不能访问
addressLink
,这是我在ShipmentData构建过程中需要的


如何使用反应式方法处理此类场景?我正在考虑收集一些外部变量中的所有数据,然后将所有数据传递给
createShipmentData
方法。但对我来说,这听起来像是一种代码味道。

最简单的方法是使用嵌套来保持对需要引用的变量的访问。以下链为您提供了一个可观察的

添加一个助手方法可以清除一些:

private Observable<Address> getAddresses(Person person) {
  return Observable.fromIterable(person.getAddressesLinks())
      .flatMapSingle(addressLink -> addressRepository.findAddressByLink(addressLink));
}

Observable.fromIterable(entity.getDataCollection())
    .flatMap(someData -> personRepository.loadById(someData.getPersonId())
        .flatMapObservable(person -> getAddresses(person)
            .map(address -> createShipmentData(someData, person, address))
        )
    )
私有可观察getAddresses(个人){
返回Observable.fromIterable(person.getAddressesLinks())
.flatMapSingle(addressLink->addressRepository.findAddressByLink(addressLink));
}
Observable.fromIterable(entity.getDataCollection())
.flatMap(someData->personRepository.loadById(someData.getPersonId())
.flatmap可观察(个人->获取地址(个人)
.map(地址->createShipmentData(某些数据、个人、地址))
)
)

您也可以使用一些技术来使用容器类(如元组或对)来传递链中所需的所有参数,但我认为这通常不值得努力。

Hm,因此简单嵌套是处理此类链的一种好方法。所有伟大的事情都很简单。
Observable.fromIterable(entity.getDataCollection())
    .flatMapSingle(someData -> personRepository.loadById(someData.getPersonId()))
    .flatMapIterable(person -> person.getAddressesLinks())
    .flatMapSingle(addressLink -> addressRepository.findAddressByLink(addressLink))
    .map(address -> createShipmentData(address))
    ...
    
private createShipmentData(Address address) {
    ShipmentData data = new ShipmentData();
    
    data.setTargetId(...); // Person.addressLink
    data.setRecepientId(...); // SomeEntity.someData.personId
    data.setPrice(...); // SomeEntity.price
    data.setSourceId(...); //SomeEntity.someData.id
    data.setCreationDate(LocalDateTime.now());

    return data;
}
Observable.fromIterable(entity.getDataCollection())
    .flatMap(someData -> personRepository.loadById(someData.getPersonId())
        .flatMapObservable(person -> Observable.fromIterable(person.getAddressesLinks())
            .flatMapSingle(addressLink -> addressRepository.findAddressByLink(addressLink))
            .map(address -> createShipmentData(someData, person, address))
        )
    )
private Observable<Address> getAddresses(Person person) {
  return Observable.fromIterable(person.getAddressesLinks())
      .flatMapSingle(addressLink -> addressRepository.findAddressByLink(addressLink));
}

Observable.fromIterable(entity.getDataCollection())
    .flatMap(someData -> personRepository.loadById(someData.getPersonId())
        .flatMapObservable(person -> getAddresses(person)
            .map(address -> createShipmentData(someData, person, address))
        )
    )