flux 中 filter 的使用和原理

本文详细介绍了ReactiveX中的filter和filterWhen操作符。filter用于根据给定条件过滤流中的元素,而filterWhen则更进一步,它接受一个函数,该函数将每个元素转换为一个发布者,然后根据这些发布者返回的boolean值决定是否保留元素。文章通过示例代码和原理分析,揭示了这两个操作符在流处理中的工作机制。
摘要由CSDN通过智能技术生成


前言


filter 用于对发布的元素进行过滤。


一、filter

1、示例

	@Test
    public void filter() {
        Flux.range(0, 5).filter(i -> i > 2).subscribe(System.out::println);
    }

2、原理

(1)FluxFilterFuseable

创建 FilterFuseableConditionalSubscriber 或 FilterFuseableSubscriber

	@Override
	public CoreSubscriber<? super T> subscribeOrReturn(CoreSubscriber<? super T> actual) {
		if (actual instanceof ConditionalSubscriber) {
			return new FilterFuseableConditionalSubscriber<>((ConditionalSubscriber<? super T>) actual,
					predicate);
		}
		return new FilterFuseableSubscriber<>(actual, predicate);
	}

(2)FilterFuseableSubscriber

		@Override
		public boolean tryOnNext(T t) {
			//请求完成,丢弃元素
			if (done) {
				Operators.onNextDropped(t, this.ctx);
				return false;
			}

			boolean b;

			//校验条件
			try {
				b = predicate.test(t);
			}
			catch (Throwable e) {
				Throwable e_ = Operators.onNextError(t, e, this.ctx, s);
				if (e_ != null) {
					onError(e_);
				}
				Operators.onDiscard(t, this.ctx);
				return false;
			}
			//条件通过,将元素发送给订阅者
			if (b) {
				actual.onNext(t);
				return true;
			}
			//条件不通过,丢弃元素
			Operators.onDiscard(t, this.ctx);
			return false;
		}

二、filterWhen

传入 Function 将T转换成 Publisher<Boolean> ,根据返回的boolean来过滤元素

1、示例

	@Test
    public void filterWhen() {
        Flux.range(0, 5)
                .filterWhen(i -> Mono.just(i).map(v -> v != 2))
                .subscribe(System.out::println);
    }

2、原理

(1)FluxFilterWhen

创建 FluxFilterWhenSubscriber

	@Override
	public CoreSubscriber<? super T> subscribeOrReturn(CoreSubscriber<? super T> actual) {
		return new FluxFilterWhenSubscriber<>(actual, asyncPredicate, bufferSize);
	}

(2)FluxFilterWhenSubscriber

		@Override
		public void onNext(T t) {
			long pi = producerIndex;
			int m = toFilter.length() - 1;

			int offset = (int)pi & m;
			//将元素存入 toFilter
			toFilter.lazySet(offset, t);
			producerIndex = pi + 1;
			//具体的逻辑
			drain();
		}

(3)drain()

void drain() {
			if (WIP.getAndIncrement(this) != 0) {
				return;
			}

			int missed = 1;
			int limit = Operators.unboundedOrLimit(bufferSize);
			long e = emitted;
			long ci = consumerIndex;
			int f = consumed;
			int m = toFilter.length() - 1;
			Subscriber<? super T> a = actual;

			for (;;) {
				long r = requested;

				while (e != r) {
					if (cancelled) {
						clear();
						return;
					}

					boolean d = done;

					int offset = (int)ci & m;
					T t = toFilter.get(offset);
					boolean empty = t == null;

					//校验是否请求数据结束或元素是否为 null
					if (d && empty) {
						Throwable ex = Exceptions.terminate(ERROR, this);
						if (ex == null) {
							a.onComplete();
						} else {
							a.onError(ex);
						}
						return;
					}
					
					//值是 null,或者值已经处理过 被设置为了 null,退出当前循环,然后继续处理下一个元素
					if (empty) {
						break;
					}

					int s = state;
					//初始状态
					if (s == STATE_FRESH) {
						Publisher<Boolean> p;

						try {
							//获取到 Publisher<Boolean>
							p = Objects.requireNonNull(asyncPredicate.apply(t), "The asyncPredicate returned a null value");
						} catch (Throwable ex) {
							Exceptions.throwIfFatal(ex);
							Exceptions.addThrowable(ERROR, this, ex);
							p = null; //discarded as "old" below
						}

						if (p != null) {
							if (p instanceof Callable) {
								Boolean u;

								try {
									u = ((Callable<Boolean>)p).call();
								} catch (Throwable ex) {
									Exceptions.throwIfFatal(ex);
									Exceptions.addThrowable(ERROR, this, ex);
									u = null; //triggers discard below
								}

								if (u != null && u) {
									a.onNext(t);
									e++;
								}
								else {
									Operators.onDiscard(t, ctx);
								}
							} else {
								//创建 FilterWhenInner ,并将当前类对象 FluxFilterWhenSubscriber 作为 parent 传入
								FilterWhenInner inner = new FilterWhenInner(this, !(p instanceof Mono));
								if (CURRENT.compareAndSet(this,null, inner)) {
									state = STATE_RUNNING;
									//FilterWhenInner 作为 Publisher<Boolean> 的订阅者
									p.subscribe(inner);
									break;
								}
							}
						}

						T old = toFilter.getAndSet(offset, null);
						Operators.onDiscard(old, ctx);
						ci++;
						if (++f == limit) {
							f = 0;
							upstream.request(limit);
						}
					} else
					if (s == STATE_RESULT) {
						//有值的状态
						Boolean u = innerResult;
						innerResult = null;

						//条件成立,将元素传递给订阅者
						if (u != null && u) {
							a.onNext(t);
							e++;
						}
						else {
							Operators.onDiscard(t, ctx);
						}
						
						//清理值
						toFilter.lazySet(offset, null);
						ci++;
						if (++f == limit) {
							f = 0;
							upstream.request(limit);
						}
						//恢复初始状态
						state = STATE_FRESH;
					} else {
						break;
					}
				}

				if (e == r) {
					if (cancelled) {
						clear();
						return;
					}

					boolean d = done;

					int offset = (int)ci & m;
					T t = toFilter.get(offset);
					boolean empty = t == null;

					if (d && empty) {
						Throwable ex = Exceptions.terminate(ERROR, this);
						if (ex == null) {
							a.onComplete();
						} else {
							a.onError(ex);
						}
						return;
					}
				}

				int w = wip;
				if (missed == w) {
					consumed = f;
					consumerIndex = ci;
					emitted = e;
					missed = WIP.addAndGet(this, -missed);
					if (missed == 0) {
						break;
					}
				} else {
					missed = w;
				}
			}
		}

(4)FilterWhenInner

上面创建了 FilterWhenInner,在 FilterWhenInner 中 的 onNext() 方法中会处理 Publisher<Boolean> 返回的 boolean 值

		@Override
		public void onNext(Boolean t) {
			if (!done) {
				if (cancelOnNext) {
					sub.cancel();
				}
				done = true;
				//设置boolean值
				parent.innerResult(t);
			}
		}

(5)innerResult()

void innerResult(Boolean item) {
			//boolean 值
			innerResult = item;
			//修改状态,有了结果的状态
			state = STATE_RESULT;
			clearCurrent();
			drain();
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_lrs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值