Skip to content

Commit c1ed51d

Browse files
committed
Throw NoSuchElementException in the first, last and single operators when the Observable is empty
1 parent 531449e commit c1ed51d

File tree

14 files changed

+82
-64
lines changed

14 files changed

+82
-64
lines changed

language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/Observable.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1950,12 +1950,12 @@ trait Observable[+T]
19501950

19511951
/**
19521952
* Returns an Observable that emits only the very first item emitted by the source Observable, or raises an
1953-
* `IllegalArgumentException` if the source Observable is empty.
1953+
* `NoSuchElementException` if the source Observable is empty.
19541954
* <p>
19551955
* <img width="640" src="https://raw.github.com/wiki/Netflix/RxJava/images/rx-operators/first.png">
19561956
*
19571957
* @return an Observable that emits only the very first item emitted by the source Observable, or raises an
1958-
* `IllegalArgumentException` if the source Observable is empty
1958+
* `NoSuchElementException` if the source Observable is empty
19591959
* @see <a href="https://github.com/Netflix/RxJava/wiki/Filtering-Observables#wiki-first">RxJava Wiki: first()</a>
19601960
* @see "MSDN: Observable.firstAsync()"
19611961
*/
@@ -1965,12 +1965,12 @@ trait Observable[+T]
19651965

19661966
/**
19671967
* Returns an Observable that emits only the very first item emitted by the source Observable, or raises an
1968-
* `IllegalArgumentException` if the source Observable is empty.
1968+
* `NoSuchElementException` if the source Observable is empty.
19691969
* <p>
19701970
* <img width="640" src="https://raw.github.com/wiki/Netflix/RxJava/images/rx-operators/first.png">
19711971
*
19721972
* @return an Observable that emits only the very first item emitted by the source Observable, or raises an
1973-
* `IllegalArgumentException` if the source Observable is empty
1973+
* `NoSuchElementException` if the source Observable is empty
19741974
* @see <a href="https://github.com/Netflix/RxJava/wiki/Filtering-Observables#wiki-first">RxJava Wiki: first()</a>
19751975
* @see "MSDN: Observable.firstAsync()"
19761976
* @see [[Observable.first]]
@@ -1979,7 +1979,7 @@ trait Observable[+T]
19791979

19801980
/**
19811981
* Returns an Observable that emits the last item emitted by the source Observable or notifies observers of
1982-
* an `IllegalArgumentException` if the source Observable is empty.
1982+
* an `NoSuchElementException` if the source Observable is empty.
19831983
*
19841984
* <img width="640" src="https://raw.github.com/wiki/Netflix/RxJava/images/rx-operators/last.png">
19851985
*
@@ -1994,12 +1994,12 @@ trait Observable[+T]
19941994

19951995
/**
19961996
* If the source Observable completes after emitting a single item, return an Observable that emits that
1997-
* item. If the source Observable emits more than one item or no items, throw an `IllegalArgumentException`.
1997+
* item. If the source Observable emits more than one item or no items, throw an `NoSuchElementException`.
19981998
*
19991999
* <img width="640" src="https://raw.github.com/wiki/Netflix/RxJava/images/rx-operators/single.png">
20002000
*
20012001
* @return an Observable that emits the single item emitted by the source Observable
2002-
* @throws IllegalArgumentException
2002+
* @throws NoSuchElementException
20032003
* if the source emits more than one item or no items
20042004
* @see <a href="https://github.com/Netflix/RxJava/wiki/Observable-Utility-Operators#wiki-single-and-singleordefault">RxJava Wiki: single()</a>
20052005
* @see "MSDN: Observable.singleAsync()"

language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/observables/BlockingObservable.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ class BlockingObservable[+T] private[scala] (val asJava: rx.observables.Blocking
5555

5656
/**
5757
* Returns the last item emitted by a specified [[Observable]], or
58-
* throws `IllegalArgumentException` if it emits no items.
58+
* throws `NoSuchElementException` if it emits no items.
5959
*
6060
* <img width="640" src="https://github.com/Netflix/RxJava/wiki/images/rx-operators/B.last.png">
6161
*
6262
* @return the last item emitted by the source [[Observable]]
63-
* @throws IllegalArgumentException
63+
* @throws NoSuchElementException
6464
* if source contains no elements
6565
* @see <a href="https://github.com/Netflix/RxJava/wiki/Blocking-Observable-Operators#last-and-lastordefault">RxJava Wiki: last()</a>
6666
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.last.aspx">MSDN: Observable.Last</a>
@@ -71,10 +71,10 @@ class BlockingObservable[+T] private[scala] (val asJava: rx.observables.Blocking
7171

7272
/**
7373
* Returns the first item emitted by a specified [[Observable]], or
74-
* `IllegalArgumentException` if source contains no elements.
74+
* `NoSuchElementException` if source contains no elements.
7575
*
7676
* @return the first item emitted by the source [[Observable]]
77-
* @throws IllegalArgumentException
77+
* @throws NoSuchElementException
7878
* if source contains no elements
7979
* @see <a href="https://github.com/Netflix/RxJava/wiki/Blocking-Observable-Operators#first-and-firstordefault">RxJava Wiki: first()</a>
8080
* @see <a href="http://msdn.microsoft.com/en-us/library/hh229177.aspx">MSDN: Observable.First</a>
@@ -85,10 +85,10 @@ class BlockingObservable[+T] private[scala] (val asJava: rx.observables.Blocking
8585

8686
/**
8787
* Returns the first item emitted by a specified [[Observable]], or
88-
* `IllegalArgumentException` if source contains no elements.
88+
* `NoSuchElementException` if source contains no elements.
8989
*
9090
* @return the first item emitted by the source [[Observable]]
91-
* @throws IllegalArgumentException
91+
* @throws NoSuchElementException
9292
* if source contains no elements
9393
* @see <a href="https://github.com/Netflix/RxJava/wiki/Blocking-Observable-Operators#first-and-firstordefault">RxJava Wiki: first()</a>
9494
* @see <a href="http://msdn.microsoft.com/en-us/library/hh229177.aspx">MSDN: Observable.First</a>

rxjava-core/src/main/java/rx/Observable.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4545,12 +4545,12 @@ public final Observable<T> finallyDo(Action0 action) {
45454545

45464546
/**
45474547
* Returns an Observable that emits only the very first item emitted by the source Observable, or raises an
4548-
* {@code IllegalArgumentException} if the source Observable is empty.
4548+
* {@code NoSuchElementException} if the source Observable is empty.
45494549
* <p>
45504550
* <img width="640" src="https://raw.github.com/wiki/Netflix/RxJava/images/rx-operators/first.png">
45514551
*
45524552
* @return an Observable that emits only the very first item emitted by the source Observable, or raises an
4553-
* {@code IllegalArgumentException} if the source Observable is empty
4553+
* {@code NoSuchElementException} if the source Observable is empty
45544554
* @see <a href="https://github.com/Netflix/RxJava/wiki/Filtering-Observables#wiki-first">RxJava Wiki: first()</a>
45554555
* @see "MSDN: Observable.firstAsync()"
45564556
*/
@@ -4560,14 +4560,14 @@ public final Observable<T> first() {
45604560

45614561
/**
45624562
* Returns an Observable that emits only the very first item emitted by the source Observable that satisfies
4563-
* a specified condition, or raises an {@code IllegalArgumentException} if no such items are emitted.
4563+
* a specified condition, or raises an {@code NoSuchElementException} if no such items are emitted.
45644564
* <p>
45654565
* <img width="640" src="https://raw.github.com/wiki/Netflix/RxJava/images/rx-operators/firstN.png">
45664566
*
45674567
* @param predicate
45684568
* the condition that an item emitted by the source Observable has to satisfy
45694569
* @return an Observable that emits only the very first item emitted by the source Observable that satisfies
4570-
* the {@code predicate}, or raises an {@code IllegalArgumentException} if no such items are emitted
4570+
* the {@code predicate}, or raises an {@code NoSuchElementException} if no such items are emitted
45714571
* @see <a href="https://github.com/Netflix/RxJava/wiki/Filtering-Observables#wiki-first">RxJava Wiki: first()</a>
45724572
* @see "MSDN: Observable.firstAsync()"
45734573
*/
@@ -4778,7 +4778,7 @@ public final <TRight, TLeftDuration, TRightDuration, R> Observable<R> join(Obser
47784778

47794779
/**
47804780
* Returns an Observable that emits the last item emitted by the source Observable or notifies observers of
4781-
* an {@code IllegalArgumentException} if the source Observable is empty.
4781+
* an {@code NoSuchElementException} if the source Observable is empty.
47824782
* <p>
47834783
* <img width="640" src="https://raw.github.com/wiki/Netflix/RxJava/images/rx-operators/last.png">
47844784
*
@@ -4793,14 +4793,14 @@ public final Observable<T> last() {
47934793

47944794
/**
47954795
* Returns an Observable that emits only the last item emitted by the source Observable that satisfies a
4796-
* given condition, or an {@code IllegalArgumentException} if no such items are emitted.
4796+
* given condition, or an {@code NoSuchElementException} if no such items are emitted.
47974797
* <p>
47984798
* <img width="640" src="https://raw.github.com/wiki/Netflix/RxJava/images/rx-operators/last.p.png">
47994799
*
48004800
* @param predicate
48014801
* the condition any source emitted item has to satisfy
48024802
* @return an Observable that emits only the last item satisfying the given condition from the source, or an
4803-
* {@code IllegalArgumentException} if no such items are emitted
4803+
* {@code NoSuchElementException} if no such items are emitted
48044804
* @throws IllegalArgumentException
48054805
* if no items that match the predicate are emitted by the source Observable
48064806
* @see <a href="https://github.com/Netflix/RxJava/wiki/Filtering-Observable-Operators#wiki-last">RxJava Wiki: last()</a>
@@ -6205,13 +6205,15 @@ public final Observable<T> serialize() {
62056205
/**
62066206
* If the source Observable completes after emitting a single item, return an Observable that emits that
62076207
* item. If the source Observable emits more than one item or no items, throw an
6208-
* {@code IllegalArgumentException}.
6208+
* {@code NoSuchElementException}.
62096209
* <p>
62106210
* <img width="640" src="https://raw.github.com/wiki/Netflix/RxJava/images/rx-operators/single.png">
62116211
*
62126212
* @return an Observable that emits the single item emitted by the source Observable
62136213
* @throws IllegalArgumentException
6214-
* if the source emits more than one item or no items
6214+
* if the source emits more than one item
6215+
* @throws NoSuchElementException
6216+
* if the source emits no items
62156217
* @see <a href="https://github.com/Netflix/RxJava/wiki/Observable-Utility-Operators#wiki-single-and-singleordefault">RxJava Wiki: single()</a>
62166218
* @see "MSDN: Observable.singleAsync()"
62176219
*/
@@ -6222,7 +6224,7 @@ public final Observable<T> single() {
62226224
/**
62236225
* If the Observable completes after emitting a single item that matches a specified predicate, return an
62246226
* Observable that emits that item. If the source Observable emits more than one such item or no such items,
6225-
* throw an {@code IllegalArgumentException}.
6227+
* throw an {@code NoSuchElementException}.
62266228
* <p>
62276229
* <img width="640" src="https://raw.github.com/wiki/Netflix/RxJava/images/rx-operators/single.p.png">
62286230
*
@@ -6231,8 +6233,9 @@ public final Observable<T> single() {
62316233
* @return an Observable that emits the single item emitted by the source Observable that matches the
62326234
* predicate
62336235
* @throws IllegalArgumentException
6234-
* if the source Observable emits either more than one item that matches the predicate or no
6235-
* items that match the predicate
6236+
* if the source Observable emits more than one item that matches the predicate
6237+
* @throws NoSuchElementException
6238+
* if the source Observable emits no item that matches the predicate
62366239
* @see <a href="https://github.com/Netflix/RxJava/wiki/Observable-Utility-Operators#wiki-single-and-singleordefault">RxJava Wiki: single()</a>
62376240
* @see "MSDN: Observable.singleAsync()"
62386241
*/

rxjava-core/src/main/java/rx/observables/BlockingObservable.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,10 @@ public Iterator<T> getIterator() {
163163

164164
/**
165165
* Returns the first item emitted by a specified {@link Observable}, or
166-
* <code>IllegalArgumentException</code> if source contains no elements.
166+
* <code>NoSuchElementException</code> if source contains no elements.
167167
*
168168
* @return the first item emitted by the source {@link Observable}
169-
* @throws IllegalArgumentException
169+
* @throws NoSuchElementException
170170
* if source contains no elements
171171
* @see <a href="https://github.com/Netflix/RxJava/wiki/Blocking-Observable-Operators#first-and-firstordefault">RxJava Wiki: first()</a>
172172
* @see <a href="http://msdn.microsoft.com/en-us/library/hh229177.aspx">MSDN: Observable.First</a>
@@ -177,14 +177,14 @@ public T first() {
177177

178178
/**
179179
* Returns the first item emitted by a specified {@link Observable} that
180-
* matches a predicate, or <code>IllegalArgumentException</code> if no such
180+
* matches a predicate, or <code>NoSuchElementException</code> if no such
181181
* item is emitted.
182182
*
183183
* @param predicate
184184
* a predicate function to evaluate items emitted by the {@link Observable}
185185
* @return the first item emitted by the {@link Observable} that matches the
186186
* predicate
187-
* @throws IllegalArgumentException
187+
* @throws NoSuchElementException
188188
* if no such items are emitted
189189
* @see <a href="https://github.com/Netflix/RxJava/wiki/Blocking-Observable-Operators#first-and-firstordefault">RxJava Wiki: first()</a>
190190
* @see <a href="http://msdn.microsoft.com/en-us/library/hh229739.aspx">MSDN: Observable.First</a>
@@ -227,12 +227,12 @@ public T firstOrDefault(T defaultValue, Func1<? super T, Boolean> predicate) {
227227

228228
/**
229229
* Returns the last item emitted by a specified {@link Observable}, or
230-
* throws <code>IllegalArgumentException</code> if it emits no items.
230+
* throws <code>NoSuchElementException</code> if it emits no items.
231231
* <p>
232232
* <img width="640" src="https://github.com/Netflix/RxJava/wiki/images/rx-operators/B.last.png">
233233
*
234234
* @return the last item emitted by the source {@link Observable}
235-
* @throws IllegalArgumentException
235+
* @throws NoSuchElementException
236236
* if source contains no elements
237237
* @see <a href="https://github.com/Netflix/RxJava/wiki/Blocking-Observable-Operators#last-and-lastordefault">RxJava Wiki: last()</a>
238238
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.last.aspx">MSDN: Observable.Last</a>
@@ -243,7 +243,7 @@ public T last() {
243243

244244
/**
245245
* Returns the last item emitted by a specified {@link Observable} that
246-
* matches a predicate, or throws <code>IllegalArgumentException</code> if
246+
* matches a predicate, or throws <code>NoSuchElementException</code> if
247247
* it emits no such items.
248248
* <p>
249249
* <img width="640" src="https://github.com/Netflix/RxJava/wiki/images/rx-operators/B.last.p.png">
@@ -252,7 +252,7 @@ public T last() {
252252
* a predicate function to evaluate items emitted by the {@link Observable}
253253
* @return the last item emitted by the {@link Observable} that matches the
254254
* predicate
255-
* @throws IllegalArgumentException
255+
* @throws NoSuchElementException
256256
* if no such items are emitted
257257
* @see <a href="https://github.com/Netflix/RxJava/wiki/Blocking-Observable-Operators#last-and-lastordefault">RxJava Wiki: last()</a>
258258
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.last.aspx">MSDN: Observable.Last</a>
@@ -349,7 +349,7 @@ public Iterable<T> latest() {
349349

350350
/**
351351
* If the {@link Observable} completes after emitting a single item, return
352-
* that item, otherwise throw an <code>IllegalArgumentException</code>.
352+
* that item, otherwise throw an <code>NoSuchElementException</code>.
353353
* <p>
354354
* <img width="640" src="https://github.com/Netflix/RxJava/wiki/images/rx-operators/B.single.png">
355355
*
@@ -364,7 +364,7 @@ public T single() {
364364
/**
365365
* If the {@link Observable} completes after emitting a single item that
366366
* matches a given predicate, return that item, otherwise throw an
367-
* <code>IllegalArgumentException</code>.
367+
* <code>NoSuchElementException</code>.
368368
* <p>
369369
* <img width="640" src="https://github.com/Netflix/RxJava/wiki/images/rx-operators/B.single.p.png">
370370
*

rxjava-core/src/main/java/rx/operators/OperatorSingle.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package rx.operators;
1717

18+
import java.util.NoSuchElementException;
19+
1820
import rx.Observable.Operator;
1921
import rx.Subscriber;
2022

@@ -73,7 +75,7 @@ public void onCompleted() {
7375
subscriber.onNext(defaultValue);
7476
subscriber.onCompleted();
7577
} else {
76-
subscriber.onError(new IllegalArgumentException("Sequence contains no elements"));
78+
subscriber.onError(new NoSuchElementException("Sequence contains no elements"));
7779
}
7880
}
7981
}

rxjava-core/src/test/java/rx/ObservableTests.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.Arrays;
2424
import java.util.LinkedList;
2525
import java.util.List;
26+
import java.util.NoSuchElementException;
2627
import java.util.concurrent.CountDownLatch;
2728
import java.util.concurrent.TimeUnit;
2829
import java.util.concurrent.atomic.AtomicInteger;
@@ -204,7 +205,7 @@ public void testFirstOfNone() {
204205
observable.first().subscribe(w);
205206
verify(w, never()).onNext(anyInt());
206207
verify(w, never()).onCompleted();
207-
verify(w, times(1)).onError(isA(IllegalArgumentException.class));
208+
verify(w, times(1)).onError(isA(NoSuchElementException.class));
208209
}
209210

210211
@Test
@@ -213,7 +214,7 @@ public void testFirstWithPredicateOfNoneMatchingThePredicate() {
213214
observable.first(IS_EVEN).subscribe(w);
214215
verify(w, never()).onNext(anyInt());
215216
verify(w, never()).onCompleted();
216-
verify(w, times(1)).onError(isA(IllegalArgumentException.class));
217+
verify(w, times(1)).onError(isA(NoSuchElementException.class));
217218
}
218219

219220
@Test
@@ -233,9 +234,9 @@ public Integer call(Integer t1, Integer t2) {
233234
}
234235

235236
/**
236-
* A reduce should fail with an IllegalArgumentException if done on an empty Observable.
237+
* A reduce should fail with an NoSuchElementException if done on an empty Observable.
237238
*/
238-
@Test(expected = IllegalArgumentException.class)
239+
@Test(expected = NoSuchElementException.class)
239240
public void testReduceWithEmptyObservable() {
240241
Observable<Integer> observable = Observable.range(1, 0);
241242
observable.reduce(new Func2<Integer, Integer, Integer>() {

rxjava-core/src/test/java/rx/ZipTests.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Collections;
2222
import java.util.HashMap;
2323
import java.util.Map;
24+
import java.util.NoSuchElementException;
2425

2526
import org.junit.Test;
2627

@@ -100,9 +101,9 @@ public void testCovarianceOfZip() {
100101
* Occasionally zip may be invoked with 0 observables. Test that we don't block indefinitely instead
101102
* of immediately invoking zip with 0 argument.
102103
*
103-
* We now expect an IllegalArgumentException since last() requires at least one value and nothing will be emitted.
104+
* We now expect an NoSuchElementException since last() requires at least one value and nothing will be emitted.
104105
*/
105-
@Test(expected = IllegalArgumentException.class)
106+
@Test(expected = NoSuchElementException.class)
106107
public void nonBlockingObservable() {
107108

108109
final Object invoked = new Object();

0 commit comments

Comments
 (0)