我可以创建一个具有整数{1,2,3}的Source,并使用Broadcast它将创建N个源,每个将有{1,2,3}。
我想做相反的事情,我有N个源,每个应该提供完全相同的整数{1,2,3}并使用???我想创建单个Source,它将具有{1,2,3}。
我会打电话给我的操作???因为我没有更好的名字所以“内爆”。
要回答你脑海中浮现的明显问题:“为什么要做这个奇怪的事情,而不仅仅是采取任何这些来源”我必须注意,那些N来源预期提供相同的数据,但实际上有些可能根本没有回应。如果他们会回复不同的数据怎么办?这是违反我们的业务逻辑的错误,因此抛出异常是可以的。
实施例: 我有两个整数来源(A和B),都有{1,2,3}。现在我同时问他们两个Integer。源B使用整数1以比A更快的响应,因此我作为内爆源立即响应1(甚至没有等待来自源A的答案)。
现在我向两个Source询问下一个元素,这次A用2响应得更快(我忽略它是1)而且我在没有等待B的情况下返回2。
现在我向两个Source询问下一个元素,并且A抛出ConnectionLostBecauseReasonsException但是B以3响应,因此内部返回3并且一切正常。
所以这里的优势就是速度 - 我的内爆源速度和最快的源数一样快,我加上它可以保护我免受N-1来源的异常。
最后,我正在尝试实现以下功能:
<T> Source<T, ?> implode(List<Source<T, ?>> sources);
我最接近的是使用Zip - 等待来自所有N个源的结果,然后(通过使用我的函数)返回其中任何一个。它确实使我免受异常的影响,但是让我像最慢的一样快,这不是我想要的。
是否已经实施了像我的“内爆”这样的策略?如果是的话,它的名字是什么?如果不是,我该如何自己实施?
以下是我的尝试:
class Multi
{
static <T> Source<T, ?> merger(List<Source<T, ?>> sources)
{
switch(sources.size())
{
case 0: throw new RuntimeException("No sources provided!");
case 1: return sources.get(0);
default: return Source.zipWithN(Multi::zip, sources);
}
}
private static <T> T zip(List<T> list)
{
return list
.stream()
.reduce(Multi::same)
.orElseThrow(RuntimeException::new);
}
private static <T> T same(T first, T second)
{
if(Objects.equals(first, second))
{
return first;
}
else
{
throw new RuntimeException();
}
}
public static void main(String[] args)
{
Source<Integer, ?> source1 = Source.from(Arrays.asList(1, 2, 3, 4));
Source<Integer, ?> source2 = Source.from(Arrays.asList(1, 2, 3));
Source<Integer, ?> merger = merger(Arrays.asList(source1, source2));
merger
.runForeach(System.out::println, ActorMaterializer.create(ActorSystem.create()))
.thenRun(() -> System.out.println("done"));
}
}
此代码输出:1 2 3完成
我希望:1 2 3 4完成
但是,我的zip方法只调用了三次,所以我没有机会这样做。第二个问题是我等待所有来源,而不是尽可能快地返回值。它涵盖了我在值不同时抛出异常的情况,因此
Source<Integer, ?> source1 = Source.from(Arrays.asList(1, 2, 4));
Source<Integer, ?> source2 = Source.from(Arrays.asList(1, 2, 3));
输出:1 2例外
正如所料。