选取元素直到某个字符并将其与RxJava分组

前端之家收集整理的这篇文章主要介绍了选取元素直到某个字符并将其与RxJava分组 前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我对问题有一个简单的设置,但解决方案似乎更复杂.

设置:我有一个热的观察者,它起源于扫描仪,扫描仪将在编码完成时发出每个数字作为不同的元素,并发出R.

问题:从这开始,我想要一个热的可观察对象,它将每个完整代码作为1个元素发出.

RxMarbles example

我尝试过使用不同的flatMap,takeUntil和groupByoperators,但是还没有找到解决方案.

最佳答案
您可以使用缓冲区运算符.

  1. PublishSubject<Token<Integer>> s = PublishSubject.create();
  2. Observable<Token<Integer>> markers = s.filter(x->x.isMarker());
  3. s.buffer(markers).subscribe(
  4. v->{
  5. Optional<Integer> reduce = v.stream()
  6. .filter(t->!t.isMarker())
  7. .map(t->(ValueToken<Integer>)t)
  8. .map(ValueToken::get)
  9. .reduce((a,b)->a+b);
  10. reduce.ifPresent(System.out::println);
  11. }
  12. );
  13. s.onNext(value(12));
  14. s.onNext(value(13));
  15. s.onNext(marker()); // will emit 25
  16. s.onNext(value(10));
  17. s.onNext(value(7));
  18. s.onNext(marker()); // will emit 17
  19. s.onNext(value(10));
  20. s.onNext(value(7)); // Not emitting yet

我创建了一个类,以在流中包装值和标记.

  1. public abstract class Token<T> {
  2. private static final MarkerToken MARKER = new MarkerToken<>();
  3. public boolean isMarker() {
  4. return false;
  5. }
  6. public static <T> MarkerToken<T> marker() {
  7. return MARKER;
  8. }
  9. public static <T> ValueToken<T> value(T o) {
  10. return new ValueToken<>(o);
  11. }
  12. public static class ValueToken<T> extends Token<T> {
  13. T value;
  14. public ValueToken(T value) {
  15. this.value = value;
  16. }
  17. public T get() {
  18. return value;
  19. }
  20. }
  21. public static class MarkerToken<T> extends Token<T> {
  22. public boolean isMarker() {
  23. return true;
  24. }
  25. }
  26. }

更新(使用扫描)

前一种方法也将在流关闭时发出,使用此解决方案,您只能发出完整的缓冲区.

消息类用作累加器,它将累加令牌,直到累加结束标记为止.

发生这种情况时,下一条消息将从头开始.

结束标记作为最后一个元素的存在将消息标记为完成.

  1. public static class Message<T> {
  2. List<Token<T>> tokens = new ArrayList<>();
  3. public Message<T> append(Token<T> t) {
  4. Message<T> mx = new Message<T>();
  5. if(!isComplete()) {
  6. mx.tokens.addAll(tokens);
  7. }
  8. mx.tokens.add(t);
  9. return mx;
  10. }
  11. public boolean isComplete() {
  12. int n = tokens.size();
  13. return n>0 && tokens.get(n-1).isMarker();
  14. }
  15. public Optional<List<Token<T>>> fullMessage(){
  16. return isComplete() ? Optional.of(tokens):Optional.empty();
  17. }
  18. }

扫描源,您为发出的每个令牌发出消息,然后过滤掉不完整的消息,仅发出标记为已完成的消息.

  1. s.scan(new Message<Integer>(),(a,b) -> a.append(b))
  2. .filter(Message::isComplete)
  3. .map(Message::fullMessage)
  4. .map(Optional::get).subscribe(v -> {
  5. System.out.println(v);
  6. });
  7. s.onNext(value(12));
  8. s.onNext(value(13));
  9. s.onNext(marker());// [V(12),V(13),MARKER]
  10. s.onNext(value(10));
  11. s.onNext(value(7));
  12. s.onNext(marker()); // [V(10),V(7),MARKER]
  13. s.onNext(value(10));
  14. s.onNext(value(127));
  15. s.onComplete(); // Not emitting incomplete messages on the closing of the subject.

猜你在找的Java相关文章