Skip to content

Commit bd38371

Browse files
author
jmhofer
committed
Added the two variants of the first operator.
1 parent 73a4ed2 commit bd38371

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package rx;
1717

18+
import static rx.util.functions.Functions.not;
19+
1820
import java.util.ArrayList;
1921
import java.util.Arrays;
2022
import java.util.Collection;
@@ -2275,6 +2277,26 @@ public Observable<T> take(final int num) {
22752277
return create(OperationTake.take(this, num));
22762278
}
22772279

2280+
/**
2281+
* Returns an Observable that emits only the very first item emitted by the source Observable.
2282+
* @return an Observable that emits only the very first item from the source, or none if the
2283+
* source Observable completes without emitting a single item.
2284+
* @see <a href="http://msdn.microsoft.com/en-us/library/hh229177%28v=vs.103%29.aspx">MSDN: Observable.First</a>
2285+
*/
2286+
public Observable<T> first() {
2287+
return take(1);
2288+
}
2289+
2290+
/**
2291+
* Returns an Observable that emits only the very first item emitted by the source Observable.
2292+
* @return an Observable that emits only the very first item from the source, or none if the
2293+
* source Observable completes without emitting a single item.
2294+
* @see <a href="http://msdn.microsoft.com/en-us/library/hh229177%28v=vs.103%29.aspx">MSDN: Observable.First</a>
2295+
*/
2296+
public Observable<T> first(Func1<? super T, Boolean> predicate) {
2297+
return skipWhile(not(predicate)).take(1);
2298+
}
2299+
22782300
/**
22792301
* Returns an Observable that emits items emitted by the source Observable so long as a
22802302
* specified condition is true.

rxjava-core/src/main/java/rx/util/functions/Functions.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,16 @@ public Void call(Object... args) {
313313
};
314314
}
315315

316+
/**
317+
* Constructs a predicate that returns true for each input that the source
318+
* predicate returns false for and vice versa.
319+
*
320+
* @param predicate The source predicate to negate.
321+
*/
322+
public static <T> Func1<T, Boolean> not(Func1<? super T, Boolean> predicate) {
323+
return new Not<T>(predicate);
324+
}
325+
316326
public static <T> Func1<? super T, Boolean> alwaysTrue() {
317327
return AlwaysTrue.INSTANCE;
318328
}
@@ -334,4 +344,5 @@ public Boolean call(Object o) {
334344
return true;
335345
}
336346
}
347+
337348
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Copyright 2013 Netflix, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package rx.util.functions;
17+
18+
/**
19+
* Implements the negation of a predicate.
20+
*
21+
* @param <T> The type of the single input parameter.
22+
*/
23+
public class Not<T> implements Func1<T, Boolean> {
24+
private final Func1<? super T, Boolean> predicate;
25+
26+
/**
27+
* Constructs a predicate that returns true for each input that the source
28+
* predicate returns false for and vice versa.
29+
*
30+
* @param predicate The source predicate to negate.
31+
*/
32+
public Not(Func1<? super T, Boolean> predicate) {
33+
this.predicate = predicate;
34+
}
35+
36+
@Override
37+
public Boolean call(T param) {
38+
return !predicate.call(param);
39+
}
40+
}

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

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,21 @@
3535
import rx.subscriptions.BooleanSubscription;
3636
import rx.subscriptions.Subscriptions;
3737
import rx.util.functions.Action1;
38+
import rx.util.functions.Func1;
3839
import rx.util.functions.Func2;
3940

4041
public class ObservableTests {
4142

4243
@Mock
4344
Observer<Integer> w;
4445

46+
private static final Func1<Integer, Boolean> IS_EVEN = new Func1<Integer, Boolean>() {
47+
@Override
48+
public Boolean call(Integer value) {
49+
return value % 2 == 0;
50+
}
51+
};
52+
4553
@Before
4654
public void before() {
4755
MockitoAnnotations.initMocks(this);
@@ -73,6 +81,44 @@ public Subscription onSubscribe(Observer<? super String> Observer) {
7381
verify(aObserver, times(1)).onCompleted();
7482
}
7583

84+
@Test
85+
public void testFirstWithPredicateOfSome() {
86+
Observable<Integer> observable = Observable.from(1, 3, 5, 4, 6, 3);
87+
observable.first(IS_EVEN).subscribe(w);
88+
verify(w, times(1)).onNext(anyInt());
89+
verify(w).onNext(4);
90+
verify(w, times(1)).onCompleted();
91+
verify(w, never()).onError(any(Throwable.class));
92+
}
93+
94+
@Test
95+
public void testFirstWithPredicateOfNoneMatchingThePredicate() {
96+
Observable<Integer> observable = Observable.from(1, 3, 5, 7, 9, 7, 5, 3, 1);
97+
observable.first(IS_EVEN).subscribe(w);
98+
verify(w, never()).onNext(anyInt());
99+
verify(w, times(1)).onCompleted();
100+
verify(w, never()).onError(any(Throwable.class));
101+
}
102+
103+
@Test
104+
public void testFirstOfSome() {
105+
Observable<Integer> observable = Observable.from(1, 2, 3);
106+
observable.first().subscribe(w);
107+
verify(w, times(1)).onNext(anyInt());
108+
verify(w).onNext(1);
109+
verify(w, times(1)).onCompleted();
110+
verify(w, never()).onError(any(Throwable.class));
111+
}
112+
113+
@Test
114+
public void testFirstOfNone() {
115+
Observable<Integer> observable = Observable.empty();
116+
observable.first().subscribe(w);
117+
verify(w, never()).onNext(anyInt());
118+
verify(w, times(1)).onCompleted();
119+
verify(w, never()).onError(any(Throwable.class));
120+
}
121+
76122
@Test
77123
public void testReduce() {
78124
Observable<Integer> observable = Observable.from(1, 2, 3, 4);

0 commit comments

Comments
 (0)