rxJava2如何根据大小聚合数组

时间:2018-06-14 08:40:13

标签: rx-java2 reactive

想象一个Flowable<byte[]>发出各种大小的字节数组。我想转换这个Flowable,以便它发出固定大小的数组。我扫描了所有操作符,但找不到与此用例匹配的内容。

我看了generate,但我看不到用上游流动的字节数组来连接它的方法。我想这不是为此设计的。

1 个答案:

答案 0 :(得分:0)

这就是我提出的,它主要基于partialCollect运算符文档中的示例。再次感谢@akarnokd跳进来。

protected FlowableTransformer<byte[], byte[]> normalize(int size)
{
    return
        FlowableTransformers.partialCollect(
            (Consumer<PartialCollectEmitter<byte[], Integer, ByteBuffer, byte[]>>) emitter -> {
                Integer idx = emitter.getIndex();
                if (idx == null) {
                    idx = 0;
                }
                ByteBuffer bb = emitter.getAccumulator();
                if (bb == null) {
                    bb = ByteBuffer.allocate(size);
                    emitter.setAccumulator(bb);
                }

                if (emitter.demand() != 0) {

                    boolean d = emitter.isComplete();
                    if (emitter.size() != 0) {
                        byte[] bytes = emitter.getItem(0);

                        int delta = size - bb.position();

                        if (enoughBytesToEmit(bytes, idx, delta)) {
                            bb.put(bytes, idx, delta);
                            byte[] bytesToEmit =
                                prepareBytesToEmit(bb);
                            emitter.next(bytesToEmit);

                            if (arrayHasMoreBytes(bytes, idx, delta)) {
                                idx = idx + delta;
                            } else {
                                idx = 0;
                                emitter.dropItems(1);
                            }
                        } else {
                            bb.put(bytes, idx, bytes.length - idx);
                            emitter.dropItems(1);
                            idx = 0;
                        }
                    } else if (d) {
                        if (bb.position() != 0) {
                            byte[] result = prepareBytesToEmit(bb);
                            emitter.next(result);
                        }
                        emitter.complete();
                        return;
                    }
                }
                emitter.setIndex(idx);
            }, Functions.emptyConsumer(), 128);

}

private byte[] prepareBytesToEmit(ByteBuffer bb)
{
    int size = bb.position();
    bb.flip();
    byte[] result = new byte[size];
    bb.get(result);
    bb.clear();

    return result;
}

private boolean enoughBytesToEmit(byte[] bytes, int idx, int delta)
{
    return bytes.length - idx >= delta;
}

private boolean arrayHasMoreBytes(byte[] bytes, int idx, int delta)
{
    return idx + delta < bytes.length;
}