Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
寻找更好的方法来组合RxJava可观察对象_Java_Observable_Reactive Programming_Rx Java2_Reactivex - Fatal编程技术网

寻找更好的方法来组合RxJava可观察对象

寻找更好的方法来组合RxJava可观察对象,java,observable,reactive-programming,rx-java2,reactivex,Java,Observable,Reactive Programming,Rx Java2,Reactivex,我正在开发一个从多个来源收集数据并按顺序应用一些转换的工具。我目前正在将此功能从Java8流转换为使用ReactiveX/RxJava 下面,您可以看到演示当前RxJava实现的单元测试 虽然它有效,但我对结果还不够满意,我正在寻找如何改进它的指导 我的两个问题是: 1。每个源返回一个结果列表(列表)。因为转换需要在完整的数据集上执行,所以我需要将多个列表合并为一个列表。 现在代码如下所示: Observable<List<List<String>>> st

我正在开发一个从多个来源收集数据并按顺序应用一些转换的工具。我目前正在将此功能从Java8流转换为使用ReactiveX/RxJava

下面,您可以看到演示当前RxJava实现的单元测试

虽然它有效,但我对结果还不够满意,我正在寻找如何改进它的指导


我的两个问题是:

1。每个源返回一个结果列表(列表)。因为转换需要在完整的数据集上执行,所以我需要将多个列表合并为一个列表。

现在代码如下所示:

Observable<List<List<String>>> stage = Observable.merge(src1, src2, src3, src4);

final List<List<String>> collector = new ArrayList<>();
Single<List<List<String>>> combinedData = stage.reduce(collector, (list, items) -> {
    list.addAll(items);
    return list;
});
基本上,我需要一种方法将
Observable applyAsync(List input)
应用到输入
List
上,并在每次转换(
Observable
)上递归地继续这样做

它类似于可观察的
。reduce
,但累加器函数需要在每次迭代中更改


下面是我编写的完整单元测试代码:

import io.reactivex.Observable;
import io.reactivex.schedulers.Schedulers;
import org.mockito.ArgumentCaptor;
import org.testng.annotations.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.*;
import static org.mockito.Mockito.*;

public class ObservableTest {
    @Test
    public void testObservable() throws Exception {
        // ARRANGE
        final CountDownLatch DONE = new CountDownLatch(1);

        // init source objects
        Observable<List<List<String>>> src1 = Observable.just(makeMatrix(Arrays.asList("src11")));
        Observable<List<List<String>>> src2 = Observable.just(makeMatrix(Arrays.asList("src21", "src22")));
        Observable<List<List<String>>> src3 = Observable.just(makeMatrix(Arrays.asList("src31", "src32", "src33")));
        Observable<List<List<String>>> src4 = Observable.just(makeMatrix(Arrays.asList("src41"), Arrays.asList("src51")));

        // prepare transformations and processor
        List<Transform> transforms = Arrays.asList(new Transform(1, 100), new Transform(2, 0));
        Processor processor = spy(new Processor());


        // ACT

        // Concat sources
        Observable<List<List<String>>> stage = Observable.merge(src1, src2, src3, src4);

        // Merge individual into matrix

        // (#1) Can the reduce operation be written without the accumulator?
        final List<List<String>> collector = new ArrayList<>();
        Single<List<List<String>>> combinedData = stage.reduce(collector, (list, items) -> {
            list.addAll(items);
            return list;
        });


        // Transform
        stage = combinedData.toObservable();
        for (Transform t : transforms) {
            // (#2) Can a series of transforms be applied sequentially to a Single (List<List<String>>), without the use of a for-loop?
            stage = stage.flatMap(t::applyAsync);
        }

        // Process
        stage.doOnComplete(DONE::countDown)
                .subscribeOn(Schedulers.computation())
                .subscribe(o -> System.out.println(processor.printList(o)));

        // wait for processing to complete
        DONE.await();


        // ASSERT

        // The sources should be combined in a single matrix
        @SuppressWarnings("unchecked")
        ArgumentCaptor<List<List<String>>> resultCaptor = ArgumentCaptor.forClass(List.class);

        verify(processor, times(1)).printList(resultCaptor.capture());
        List<List<String>> resultMatrix = resultCaptor.getValue();

        // result matrix should not be null and all transformations should be applied in order (T1, T2, etc.)
        assertThat(resultMatrix, notNullValue());
        assertThat(resultMatrix.stream().flatMap(Collection::stream).collect(Collectors.toList()), everyItem(containsString("T1-T2")));
        assertThat(resultMatrix, not(hasItem(hasItem(containsString("T2-T1")))));
   }


    private List<List<String>> makeMatrix(List<String> items) {
        return Collections.singletonList(items);
    }

    private List<List<String>> makeMatrix(List<String> items, List<String> moreItems) {
        return Arrays.asList(items, moreItems);
    }

    static class Processor {
        String printList(List<List<String>> input) {
            return input.stream().map(rows -> rows.stream().collect(Collectors.joining(" | ")))
                    .collect(Collectors.joining(System.lineSeparator()));
        }
    }

    static class Transform {
        final int n;
        private final int delay;

        Transform(int n, int delay) {
            this.n = n;
            this.delay = delay;
        }

        private Observable<List<List<String>>> applyAsync(List<List<String>> input) {
            return Observable.just(input).map(this::apply).delay(delay, TimeUnit.MILLISECONDS);
        }

        private List<List<String>> apply(List<List<String>> input) {
            return input.stream()
                    .map(row -> row.stream()
                            .map(this::transform)
                            .collect(Collectors.toList())
                    )
                    .collect(Collectors.toList());
        }

        private String transform(String input) {
            return input + "-T" + n;
        }
    }
}
import io.reactivex.Observable;
导入io.reactivex.schedulers.schedulers;
导入org.mockito.ArgumentCaptor;
导入org.testng.annotations.Test;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.Collections;
导入java.util.List;
导入java.util.concurrent.CountDownLatch;
导入java.util.concurrent.TimeUnit;
导入java.util.stream.collector;
导入静态org.hamcrest.matcherasert.assertThat;
导入静态org.hamcrest.Matchers.contains;
导入静态org.hamcrest.Matchers.*;
导入静态org.mockito.mockito.*;
公共类可观测测试{
@试验
public void testObservable()引发异常{
//安排
最终倒计时锁存器完成=新倒计时锁存器(1);
//初始化源对象
可观测的src1=可观测的.just(makeMatrix(Arrays.asList(“src11”));
Observable src2=Observable.just(makeMatrix(Arrays.asList(“src21”、“src22”));
Observable src3=Observable.just(makeMatrix(Arrays.asList(“src31”、“src32”、“src33”));
Observable src4=Observable.just(makeMatrix(Arrays.asList(“src41”)、Arrays.asList(“src51”);
//准备转换和处理器
列表转换=数组.asList(新转换(1100),新转换(2,0));
处理器处理器=间谍(新处理器());
//表演
//海螺源
可观察阶段=可观察的合并(src1、src2、src3、src4);
//将个体合并到矩阵中
//(#1)在没有累加器的情况下是否可以写入reduce操作?
最终列表收集器=新的ArrayList();
Single combinedData=stage.reduce(收集器,(列表,项目)->{
列表。添加所有(项目);
退货清单;
});
//转化
stage=combinedData.toObservable();
for(变换t:变换){
//(#2)一系列变换是否可以顺序应用于单个(列表),而不使用for循环?
stage=stage.flatMap(t::applyAsync);
}
//过程
stage.doOnComplete(完成:倒计时)
.subscribeOn(Schedulers.computation())
.subscribe(o->System.out.println(processor.printList(o));
//等待处理完成
完成。等待();
//断言
//源应组合在单个矩阵中
@抑制警告(“未选中”)
ArgumentCaptor resultCaptor=ArgumentCaptor.forClass(List.class);
验证(处理器,次(1)).printList(resultCaptor.capture());
List resultMatrix=resultCaptor.getValue();
//结果矩阵不应为空,所有转换应按顺序应用(T1、T2等)
断言(resultMatrix,notNullValue());
断言(resultMatrix.stream().flatMap(Collection::stream).collect(Collectors.toList()),everyItem(containssString(“T1-T2”);
资产(resultMatrix,非(hasItem)(hasItem(containssString(“T2-T1”;)))));
}
私有列表生成矩阵(列表项){
返回集合。单件列表(项目);
}
私有列表生成矩阵(列表项,列表项){
返回数组.asList(items,moreItems);
}
静态类处理器{
字符串打印列表(列表输入){
返回input.stream().map(行->行.stream().collect(收集器.连接(“|”))
.collect(收集器.joining(System.lineSeparator());
}
}
静态类变换{
最终整数n;
私人最终整数延迟;
变换(整数n,整数延迟){
这个,n=n;
延迟=延迟;
}
私有可观察ApplySync(列表输入){
返回Observable.just(input).map(this::apply).delay(delay,TimeUnit.ms);
}
私有列表应用(列表输入){
返回input.stream()
.map(行->行.stream()
.map(this::transform)
.collect(收集器.toList())
)
.collect(Collectors.toList());
}
私有字符串转换(字符串输入){
返回输入+“-T”+n;
}
}
}
如果要运行,请导入以下Maven依赖项:

<dependency>
    <groupId>io.reactivex.rxjava2</groupId>
    <artifactId>rxjava</artifactId>
    <version>2.1.0</version>
</dependency>
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-all</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.4.3</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>6.10</version>
    <scope>test</scope>
</dependency>

io.reactivex.rxjava2
rxjava
2.1.0
org.hamcrest
汉克雷斯特酒店
1.3
测试
org.mockito
莫基托磁芯
2.4.3
测试
org.testng
testng
6.10
测试

免责声明:我没有任何特定于RxJava的经验,只有RxJS、Rx.NET和RxSwift

1. 您应该能够直接传递
ArrayList
的新实例:

Single<List<List<String>>> combinedData = stage.reduce(new ArrayList<>(), (list, items) -> {
    list.addAll(items);
    return list;
});
Single combinedData=stage.reduce(新的ArrayList(),(列表,项)->{
列表。添加所有(项目);
退货清单;
});
它将仅用作蓄能器的初始种子;在第一次打电话到洛杉矶之后
Single<List<List<String>>> combinedData = stage.reduce(new ArrayList<>(), (list, items) -> {
    list.addAll(items);
    return list;
});
// Put this somewhere
public IObservable<List<List<String>> handleTransforms(
    Observable<List<List<String>>> currentStage
    List<Transform> ts){

    return currentStage.flatMap(t[0]::applyAsync)
        .flatMap(newStage -> handleTransforms(newStage, ts.stream().skip(1).toList()))
}

// And then use it like this
stage = handleTransforms(stage, transforms);