Skip to content

Commit 04b57c2

Browse files
Merge pull request ReactiveX#156 from mairbek/toIterable
Implemented ToIterable Operation
2 parents 5d8a13e + f805834 commit 04b57c2

File tree

2 files changed

+163
-8
lines changed

2 files changed

+163
-8
lines changed

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

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

18+
import static org.junit.Assert.assertEquals;
1819
import static org.mockito.Matchers.*;
1920
import static org.mockito.Mockito.*;
2021

21-
import java.util.ArrayList;
22-
import java.util.Arrays;
23-
import java.util.List;
24-
import java.util.Map;
25-
import java.util.concurrent.CountDownLatch;
26-
import java.util.concurrent.Future;
27-
import java.util.concurrent.TimeUnit;
28-
import java.util.concurrent.TimeoutException;
22+
import java.util.*;
23+
import java.util.concurrent.*;
2924
import java.util.concurrent.atomic.AtomicReference;
3025

3126
import org.junit.Before;
@@ -58,6 +53,7 @@
5853
import rx.plugins.RxJavaPlugins;
5954
import rx.util.AtomicObservableSubscription;
6055
import rx.util.AtomicObserver;
56+
import rx.util.Exceptions;
6157
import rx.util.Range;
6258
import rx.util.functions.Action0;
6359
import rx.util.functions.Action1;
@@ -1524,6 +1520,79 @@ public static <T> Observable<List<T>> toList(final Observable<T> that) {
15241520
return _create(OperationToObservableList.toObservableList(that));
15251521
}
15261522

1523+
/**
1524+
* Converts an observable sequence to an Iterable.
1525+
*
1526+
* @param that the source Observable
1527+
* @return Observable converted to Iterable.
1528+
*/
1529+
public static <T> Iterable<T> toIterable(final Observable<T> that) {
1530+
final BlockingQueue<Notification<T>> notifications = new LinkedBlockingQueue<Notification<T>>();
1531+
1532+
materialize(that).subscribe(new Observer<Notification<T>>() {
1533+
@Override
1534+
public void onCompleted() {
1535+
// ignore
1536+
}
1537+
1538+
@Override
1539+
public void onError(Exception e) {
1540+
// ignore
1541+
}
1542+
1543+
@Override
1544+
public void onNext(Notification<T> args) {
1545+
notifications.offer(args);
1546+
}
1547+
});
1548+
1549+
final Iterator<T> it = new Iterator<T>() {
1550+
private Notification<T> buf;
1551+
1552+
@Override
1553+
public boolean hasNext() {
1554+
if (buf == null) {
1555+
buf = take();
1556+
}
1557+
return !buf.isOnCompleted();
1558+
}
1559+
1560+
@Override
1561+
public T next() {
1562+
if (buf == null) {
1563+
buf = take();
1564+
}
1565+
if (buf.isOnError()) {
1566+
throw Exceptions.propagate(buf.getException());
1567+
}
1568+
1569+
T result = buf.getValue();
1570+
buf = null;
1571+
return result;
1572+
}
1573+
1574+
private Notification<T> take() {
1575+
try {
1576+
return notifications.take();
1577+
} catch (InterruptedException e) {
1578+
throw Exceptions.propagate(e);
1579+
}
1580+
}
1581+
1582+
@Override
1583+
public void remove() {
1584+
throw new UnsupportedOperationException("Read-only iterator");
1585+
}
1586+
};
1587+
1588+
return new Iterable<T>() {
1589+
@Override
1590+
public Iterator<T> iterator() {
1591+
return it;
1592+
}
1593+
};
1594+
}
1595+
15271596
/**
15281597
* Converts an Iterable sequence to an Observable sequence.
15291598
*
@@ -2544,6 +2613,15 @@ public Observable<List<T>> toSortedList(final Object sortFunction) {
25442613
return toSortedList(this, sortFunction);
25452614
}
25462615

2616+
/**
2617+
* Converts an observable sequence to an Iterable.
2618+
*
2619+
* @return Observable converted to Iterable.
2620+
*/
2621+
public Iterable<T> toIterable() {
2622+
return toIterable(this);
2623+
}
2624+
25472625
public static class UnitTest {
25482626

25492627
@Mock
@@ -2623,6 +2701,52 @@ public void testSequenceEqual() {
26232701
verify(result, times(1)).onNext(false);
26242702
}
26252703

2704+
2705+
@Test
2706+
public void testToIterable() {
2707+
Observable<String> obs = toObservable("one", "two", "three");
2708+
2709+
Iterator<String> it = obs.toIterable().iterator();
2710+
2711+
assertEquals(true, it.hasNext());
2712+
assertEquals("one", it.next());
2713+
2714+
assertEquals(true, it.hasNext());
2715+
assertEquals("two", it.next());
2716+
2717+
assertEquals(true, it.hasNext());
2718+
assertEquals("three", it.next());
2719+
2720+
assertEquals(false, it.hasNext());
2721+
2722+
}
2723+
2724+
@Test(expected = TestException.class)
2725+
public void testToIterableWithException() {
2726+
Observable<String> obs = create(new Func1<Observer<String>, Subscription>() {
2727+
2728+
@Override
2729+
public Subscription call(Observer<String> observer) {
2730+
observer.onNext("one");
2731+
observer.onError(new TestException());
2732+
return Observable.noOpSubscription();
2733+
}
2734+
});
2735+
2736+
Iterator<String> it = obs.toIterable().iterator();
2737+
2738+
assertEquals(true, it.hasNext());
2739+
assertEquals("one", it.next());
2740+
2741+
assertEquals(true, it.hasNext());
2742+
it.next();
2743+
2744+
}
2745+
2746+
private static class TestException extends RuntimeException {
2747+
2748+
}
2749+
26262750
}
26272751

26282752
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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;
17+
18+
public class Exceptions {
19+
private Exceptions() {
20+
21+
}
22+
23+
public static RuntimeException propagate(Throwable t) {
24+
if (t instanceof RuntimeException) {
25+
throw (RuntimeException) t;
26+
} else {
27+
throw new RuntimeException(t);
28+
}
29+
}
30+
31+
}

0 commit comments

Comments
 (0)