如何在RxJava中返回聚合-collect()是正确的方法吗?

如何在RxJava中返回聚合-collect()是正确的方法吗?,java,rx-java,reactive-programming,Java,Rx Java,Reactive Programming,我有一个Observable,它发出“昂贵”的值来获取(想想慢速网络),我需要处理单个项目以及一些聚合。我想用一个订阅(…)就可以了。我希望Observable只为所有订户发出一次其值 我创建了一个示例来演示我的困境。在本例中,我使用一个集合作为数据源—不要因此而分心。多次运行一个集合是“便宜的”-但这不是我的用例,所以这里不要放大集合的使用;-) 我有一个简单的课程: public class Lego { public final String color; public fina

我有一个Observable,它发出“昂贵”的值来获取(想想慢速网络),我需要处理单个项目以及一些聚合。我想用一个
订阅(…)
就可以了。我希望Observable只为所有订户发出一次其值

我创建了一个示例来演示我的困境。在本例中,我使用一个集合作为数据源—不要因此而分心。多次运行一个集合是“便宜的”-但这不是我的用例,所以这里不要放大集合的使用;-)

我有一个简单的课程:

public class Lego {

  public final String color;
  public final String shape;
  public final String size;
  public final int nippels;

  public Lego(final String color, final String shape, final String size, final int nippels) {
    this.color = color;
    this.shape = shape;
    this.size = size;
    this.nippels = nippels;
  }

  @Override
  public String toString() {
    return String.format("Color: %s, Shape: %s, Size: %s, Nipples: %d",this.color,this.shape,this.size,this.nippels);
  }

}
以及这些对象的集合:

  public Observable<Lego> getLegoSample() {
    Collection<Lego> result = new ArrayList<Lego>();
    result.add(new Lego("red", "cube", "xl", 6));
    result.add(new Lego("blue", "box", "s", 2));
    result.add(new Lego("green", "cube", "l", 4));
    result.add(new Lego("yellow", "odd", "m", 3));
    result.add(new Lego("red", "sphere", "xs", 0));
    result.add(new Lego("blue", "box", "xl", 8));
    result.add(new Lego("green", "odd", "s", 1));
    result.add(new Lego("green", "odd", "m", 1));
    result.add(new Lego("green", "odd", "l", 1));
    result.add(new Lego("yellow", "odd", "m", 3));
    result.add(new Lego("blue", "box", "m", 4));
    result.add(new Lego("green", "cube", "l", 4));
    result.add(new Lego("yellow", "sphere", "m", 3));
    result.add(new Lego("red", "sphere", "xl", 7));
    result.add(new Lego("blue", "cube", "xl", 8));
    result.add(new Lego("green", "odd", "s", 1));
    result.add(new Lego("yellow", "box", "s", 1));
    result.add(new Lego("yellow", "sphere", "l", 1));
    Observable<Lego> observable = Observable.from(result);
    return observable;
  }
2问题s:

  • “collect()”是正确的方法吗(我会使用专门的集合对象,而不仅仅是HashMap)
  • 我如何组合这些序列,所以我只运行了一次我原来的可观察序列

  • 更新(9月4日):

    读报纸有帮助(我的坏习惯)。我看错了方向。为了让所有潜在订户只发射一次可观测数据,它需要是a,一个可观测数据的子类。这可以通过使用任何可观察到的数据来实现

    可连接的可观察对象在其方法被调用之前不会发出任何值

    因此,我的代码如下所示:

    ConnectableObservable co = getLegoSample().publish();
    co.subscribe();
    co.collect(new HashMap<String,Integer>(), new Action2<Map<String,Integer>,Lego>(){
    @Override
    public void call(Map<String, Integer> t1, Lego t2) {
      if (t1.containsKey(t2.color)) {
        t1.put(t2.color,(t1.get(t2.color).intValue()+1));
      } else {
        t1.put(t2.color, 1);
      }
    
    }}).subscribe();
    co.count().subscribe();
    co.map(LegotoNipples).sum().subscribe();
    co.connect();
    
    ConnectableObservable co=getLegoSample().publish();
    公司认购(;
    co.collect(新的HashMap(),新的Action2()){
    @凌驾
    公共无效呼叫(地图t1、乐高t2){
    if(t1.容器Y(t2.颜色)){
    t1.put(t2.color,(t1.get(t2.color.intValue()+1));
    }否则{
    t1.put(t2.color,1);
    }
    }}).subscribe();
    co.count().subscribe();
    co.map(LegotoNipples.sum().subscribe();
    co.connect();
    
    对于聚合,仍然是
    collect()
    的问题,最终,当使用不同的调度程序时,如何最好地进行编排(但这是有问题的)



    (是的,我一直在使用Java<8)

    您还可以使用
    Observable.groupBy
    进行聚合。考虑这个样本:

    Observable<NamedCount<String>> countStream = 
      getLegoSample()
     .groupBy(Lego::getColor)
     .flatMap(obs -> obs.count().map(count -> new NamedCount<>(obs.getKey(), count)))
    
    产生以下输出

    NamedCount{name=red, count=3}
    NamedCount{name=green, count=6}
    NamedCount{name=blue, count=4}
    NamedCount{name=yellow, count=5}
    

    将传递的thr函数更改为
    Observable.groupBy()
    可以获得其他聚合(按形状、大小等计数)

    有趣。我会试试看。现在需要找出Lego::getColor的Java6等价物这是方法引用-java 8之前的等价物是
    new Func1(){@Override public String call(Lego-Lego){return Lego.getColor();}}
    ,或者可以用lambdas
    Lego->Lego.getColor()重写它
     public class NamedCount<T> {
    
        private final T name;
        private final int count;
    
        public NamedCount(T name, int count) {
            this.name = name;
            this.count = count;
        }
    
        public T getName() {
            return name;
        }
    
        public int getCount() {
            return count;
        }
    }
    
    countStream.subscribe(System.out::println);                
    
    NamedCount{name=red, count=3}
    NamedCount{name=green, count=6}
    NamedCount{name=blue, count=4}
    NamedCount{name=yellow, count=5}