我想了解RxJava
的详细信息。
直观地,我期望first()
和take(1)
相等并做同样的事情。但是,通过挖掘源代码first()
定义为take(1).single()
。
single()
这里有什么用处?没有take(1)
已经保证输出单个项目吗?
答案 0 :(得分:35)
区别在于take(1)
将从上游中继0..1项,而first
将中继第一个元素或如果上游为空则发出错误(NoSuchElementException)。他们都没有阻止。
确实为first == take(1).single()
,其中take(1)
将上游项目数限制为1,single()
确保上游不为空。
此示例打印"完成"仅
Observable.empty().take(1)
.subscribe(System.out::println, Throwable::printStackTrace,
() -> System.out.println("Done"));
此示例打印" 1"然后是"完成":
Observable.just(1).take(1)
.subscribe(System.out::println, Throwable::printStackTrace,
() -> System.out.println("Done"));
此示例还打印" 1"然后是"完成":
Observable.just(1, 2, 3).take(1)
.subscribe(System.out::println, Throwable::printStackTrace,
() -> System.out.println("Done"));
此示例因NoSuchElementException
Observable.empty().first()
.subscribe(System.out::println, Throwable::printStackTrace,
() -> System.out.println("Done"));
此示例再次打印" 1"然后是"完成":
Observable.just(1).first()
.subscribe(System.out::println, Throwable::printStackTrace,
() -> System.out.println("Done"));
此示例再次打印" 1"然后是"完成":
Observable.just(1, 2, 3).first()
.subscribe(System.out::println, Throwable::printStackTrace,
() -> System.out.println("Done"));
此示例打印的堆栈跟踪为NoSuchElementException
,因为源包含的元素太少:
Observable.empty().single()
.subscribe(System.out::println, Throwable::printStackTrace,
() -> System.out.println("Done"));
此示例打印了一个IllegalArgumentException
的堆栈跟踪,因为源包含太多元素:
Observable.just(1, 2, 3).single()
.subscribe(System.out::println, Throwable::printStackTrace,
() -> System.out.println("Done"));
答案 1 :(得分:5)
实现的差异是由语义的差异驱动的。如果不了解语言及其内部运作,请考虑这两种方法的含义。
first()
意味着它将返回一个元素。集合中的第一个元素。
take(x)
意味着它将返回元素集合。集合中的第一个x
元素。
不同的语义需要不同的名称。不同的回报值需要不同的技术实现。
这也是可能的(再次,无需深入了解技术答案),这两种实现可能会以非常不同的方式处理错误情况。我个人希望first()
为空集合抛出异常,因为没有第一个元素。但是,如果初始集合的元素少于take(x)
,我可能会合理地期望x
返回小于x
大小的集合,而不会出现错误。 可能导致在给定空集合时返回空集合而没有错误。
此外,作为一个技术问题,像take(x)
这样的东西更有可能不会立即迭代底层集合,而是推迟到某些东西迭代它的结果。但是,first()
需要迭代并具体化底层集合的第一个元素。