如何从磁通迭代中获得独特的元素

时间:2019-08-12 18:48:15

标签: spring-webflux project-reactor

我有3个对象。 Foo由Bars组和Bar由Baz组组成。鉴于Foo,我应该如何迭代并使用distinct()来获得不同的baz和不同的柱线?

我有以下代码:


//Updated
class Foo{

     Integer fooId;
     Set<Integer> barSetOfIds ;
      //getter&setter
}

and FooRepo{
        Mono<Foo> find(Integer fooId);
    }
class Bar{
  Integer barId;
  Set<Integer> bazSetOfIds ;
//getter&setter
}
and BarRepo{
        Mono<Bar> find(Integer barId);
    }

class Baz{
     Integer bazId;
}

and BazRepo{
   Flux<Baz> find(Integer bazid);
}

所以我实际上尝试过

呼叫代码: ///某些方法


Mono<Boolean> monoPresent = fooRepo
       .find(fooId)
       .filter(i -> i.getFooId() != null)
       .hasElement();

   return monoPresent.flatMap(isPresent -> {
         if (isPresent) {
           return fooRepo.find(fooId)
               .map(fooFromDB -> {//fooFromDB is instance of Foo returned
                 fooRepo.update(fooFromDB);
                 return processDistinct(fooFromDB);
               })
               .then();
         } else {//
           return Mono.error(new SomeException("foo")
               .then();
         }
       }
   );

//below method gets called 

Flux<Integer> processDistinct(Foo pkg) {
   System.out.println("INSIDE ");
   Flux<Integer> cids = Flux.fromIterable(pkg.getBarListIds())
       .flatMap(p ->
           {
             System.out.println("barInteger=" + p.intValue());
             return barRepo.find(p);
           }
       ).flatMapIterable(
           x -> {
             System.out.println("cids=" + x.getBazListIds().size());
             return x.getBazListIds();
           }
       )
       .distinct()
       .doOnNext(x -> System.out.println("Inside doOnNext=" + x));
   //So here only on block do I see distinct values printed else code just passes
   List<Integer> list2 = cids.collectSortedList().block();
   list2.forEach(cidints -> System.out.println("cids=" + cidints));

   return cids;
 }

仅当我阻止()时,我才能看到cids(变量)值

更新: 使用Michael的建议(进行一些更改)processDistinct中的以下方法也可以使用,但仍然需要阻止,这导致我怀疑调用代码而不是processDistict [?]。

processDistinct(Foo foo){
Flux<Integer> distinctBazzFluxIds = fooRepo
       .find(foo.getFooId())
       .flatMapIterable(Foo::getBarSetOfIds)
       .flatMap(barId -> {
         return barRepo.find(barId);
       }).flatMapIterable(bar-> bar.getBazSetOdIds()).distinct()
       .doOnNext(bazId -> {
         System.out.println("Inside doOnNext"+cid);
         new SomeService().sendDistinct(cid);
       });

更新(固定): 因此,我很愚蠢地从调用流的doOnNext内部调用此processDistinct,并且我认为流正在丢失(我需要一些更好的解释)。我解决了这个问题,现在可以了。但是不确定为什么会丢失流的原因以及正确的解释。


    Mono<Boolean> monoPresent = fooRepo
        .find(fooId)
        .filter(i -> i.getFooId() != null)
        .hasElement();

    return monoPresent.flatMap(isPresent -> {
      if (isPresent) {
        return fooRepo
            .find(foo.getFooId())
            .flatMapIterable(Foo::getBarSetOfIds)
            .flatMap(barId -> {
              return barRepo.find(barId);
            }).flatMapIterable(bar -> bar.getBazSetOdIds()).distinct()
            .doOnNext(bazId -> {
              System.out.println("Inside doOnNext" + cid);
              new SomeService().sendDistinct(cid);
            }).then();
      } else {//SAVE
        return Mono.error(new SomeException("foo")
            .then();
      }
    });

1 个答案:

答案 0 :(得分:0)

您的班级结构和您的问题不匹配-目前FooBar都包含Integer的集合,而不分别包含BarBaz的集合,并且您的Repo类已经返回Flux,不可迭代。

假设问题文本正确,您将具有类似于以下内容的类结构:

class Foo {
    Integer fooId;
    Set<Bar> barSet;
}

class Bar {
    Integer barId;
    Set<Baz> bazSet;
}

class Baz {
    Integer bazId;
}

interface FooRepo {
    Iterable<Foo> findAll();
}

...然后,您可以使用以下内容来获取(例如)所有不同的Baz对象:

Flux<Baz> distinctBazzFlux = Flux.fromIterable(fooRepoInstance.findAll())
        .flatMapIterable(Foo::getBars)
        .flatMapIterable(Bar::getBazs)
        .distinct();

如果只希望使用不同的Bar对象,请删除第二个flatMapIterable()调用。

具体来说,您需要flatMapIterable()方法,因为flatMap()方法只能展平Publisher(例如另一个FluxMono)。当然,您可以先将迭代器包装在Flux中,但是flatMapIterable()是获得相同结果的更简洁,更简洁的方法。

如果根据您的评论,这些类包含整数集而不是对象本身,那么您可以采用类似的方法:

Flux<Baz> distinctBazzFlux = fooRepo.find(blah)
        .flatMapIterable(Foo::getBars)
        .map(BarRepo::find)
        .flatMapIterable(Bar::getBazs)
        .map(BazRepo::find)
        .distinct();

在任何情况下,阻塞都是错误的解决方案,因为从本质上讲,这种方法无法解决使用反应堆的问题。