Skip to content

Commit 14b701d

Browse files
committed
Operations Aggregate, Average and Sum with selector
1 parent 1586113 commit 14b701d

File tree

7 files changed

+1304
-1
lines changed

7 files changed

+1304
-1
lines changed

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

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import rx.observables.BlockingObservable;
3333
import rx.observables.ConnectableObservable;
3434
import rx.observables.GroupedObservable;
35+
import rx.operators.OperationAggregate;
3536
import rx.operators.OperationAll;
3637
import rx.operators.OperationAmb;
3738
import rx.operators.OperationAny;
@@ -4118,6 +4119,54 @@ public static Observable<Double> sumDoubles(Observable<Double> source) {
41184119
return OperationSum.sumDoubles(source);
41194120
}
41204121

4122+
/**
4123+
* Create an Observable that extracts integer values from this Observable via
4124+
* the provided function and computes the integer sum of the value sequence.
4125+
*
4126+
* @param valueExtractor the function to extract an integer from this Observable
4127+
* @return an Observable that extracts integer values from this Observable via
4128+
* the provided function and computes the integer sum of the value sequence.
4129+
*/
4130+
public Observable<Integer> sumInteger(Func1<? super T, Integer> valueExtractor) {
4131+
return create(new OperationSum.SumIntegerExtractor<T>(this, valueExtractor));
4132+
}
4133+
4134+
/**
4135+
* Create an Observable that extracts long values from this Observable via
4136+
* the provided function and computes the long sum of the value sequence.
4137+
*
4138+
* @param valueExtractor the function to extract an long from this Observable
4139+
* @return an Observable that extracts long values from this Observable via
4140+
* the provided function and computes the long sum of the value sequence.
4141+
*/
4142+
public Observable<Long> sumLong(Func1<? super T, Long> valueExtractor) {
4143+
return create(new OperationSum.SumLongExtractor<T>(this, valueExtractor));
4144+
}
4145+
4146+
/**
4147+
* Create an Observable that extracts float values from this Observable via
4148+
* the provided function and computes the float sum of the value sequence.
4149+
*
4150+
* @param valueExtractor the function to extract an float from this Observable
4151+
* @return an Observable that extracts float values from this Observable via
4152+
* the provided function and computes the float sum of the value sequence.
4153+
*/
4154+
public Observable<Float> sumFloat(Func1<? super T, Float> valueExtractor) {
4155+
return create(new OperationSum.SumFloatExtractor<T>(this, valueExtractor));
4156+
}
4157+
4158+
/**
4159+
* Create an Observable that extracts double values from this Observable via
4160+
* the provided function and computes the double sum of the value sequence.
4161+
*
4162+
* @param valueExtractor the function to extract an double from this Observable
4163+
* @return an Observable that extracts double values from this Observable via
4164+
* the provided function and computes the double sum of the value sequence.
4165+
*/
4166+
public Observable<Double> sumDouble(Func1<? super T, Double> valueExtractor) {
4167+
return create(new OperationSum.SumDoubleExtractor<T>(this, valueExtractor));
4168+
}
4169+
41214170
/**
41224171
* Returns an Observable that computes the average of the Integers emitted
41234172
* by the source Observable.
@@ -4183,6 +4232,54 @@ public static Observable<Double> averageDoubles(Observable<Double> source) {
41834232
return OperationAverage.averageDoubles(source);
41844233
}
41854234

4235+
/**
4236+
* Create an Observable that extracts integer values from this Observable via
4237+
* the provided function and computes the integer average of the value sequence.
4238+
*
4239+
* @param valueExtractor the function to extract an integer from this Observable
4240+
* @return an Observable that extracts integer values from this Observable via
4241+
* the provided function and computes the integer average of the value sequence.
4242+
*/
4243+
public Observable<Integer> averageInteger(Func1<? super T, Integer> valueExtractor) {
4244+
return create(new OperationAverage.AverageIntegerExtractor<T>(this, valueExtractor));
4245+
}
4246+
4247+
/**
4248+
* Create an Observable that extracts long values from this Observable via
4249+
* the provided function and computes the long average of the value sequence.
4250+
*
4251+
* @param valueExtractor the function to extract an long from this Observable
4252+
* @return an Observable that extracts long values from this Observable via
4253+
* the provided function and computes the long average of the value sequence.
4254+
*/
4255+
public Observable<Long> averageLong(Func1<? super T, Long> valueExtractor) {
4256+
return create(new OperationAverage.AverageLongExtractor<T>(this, valueExtractor));
4257+
}
4258+
4259+
/**
4260+
* Create an Observable that extracts float values from this Observable via
4261+
* the provided function and computes the float average of the value sequence.
4262+
*
4263+
* @param valueExtractor the function to extract an float from this Observable
4264+
* @return an Observable that extracts float values from this Observable via
4265+
* the provided function and computes the float average of the value sequence.
4266+
*/
4267+
public Observable<Float> averageFloat(Func1<? super T, Float> valueExtractor) {
4268+
return create(new OperationAverage.AverageFloatExtractor<T>(this, valueExtractor));
4269+
}
4270+
4271+
/**
4272+
* Create an Observable that extracts double values from this Observable via
4273+
* the provided function and computes the double average of the value sequence.
4274+
*
4275+
* @param valueExtractor the function to extract an double from this Observable
4276+
* @return an Observable that extracts double values from this Observable via
4277+
* the provided function and computes the double average of the value sequence.
4278+
*/
4279+
public Observable<Double> averageDouble(Func1<? super T, Double> valueExtractor) {
4280+
return create(new OperationAverage.AverageDoubleExtractor<T>(this, valueExtractor));
4281+
}
4282+
41864283
/**
41874284
* Returns an Observable that emits the minimum item emitted by the source
41884285
* Observable. If there is more than one such item, it returns the
@@ -4954,6 +5051,49 @@ public <R> Observable<R> reduce(R initialValue, Func2<R, ? super T, R> accumulat
49545051
public <R> Observable<R> aggregate(R initialValue, Func2<R, ? super T, R> accumulator) {
49555052
return reduce(initialValue, accumulator);
49565053
}
5054+
5055+
/**
5056+
* Create an Observable that aggregates the source values with the given accumulator
5057+
* function and projects the final result via the resultselector.
5058+
* <p>
5059+
* Works like the {@link #aggregate(java.lang.Object, rx.util.functions.Func2)} projected
5060+
* with {@link #map(rx.util.functions.Func1)} without the overhead of some helper
5061+
* operators.
5062+
* @param <U> the intermediate (accumulator) type
5063+
* @param <V> the result type
5064+
* @param seed the initial value of the accumulator
5065+
* @param accumulator the function that takes the current accumulator value,
5066+
* the current emitted value and returns a (new) accumulated value.
5067+
* @param resultSelector the selector to project the final value of the accumulator
5068+
* @return an Observable that aggregates the source values with the given accumulator
5069+
* function and projects the final result via the resultselector
5070+
*/
5071+
public <U, V> Observable<V> aggregate(
5072+
U seed, Func2<U, ? super T, U> accumulator,
5073+
Func1<? super U, ? extends V> resultSelector) {
5074+
return create(new OperationAggregate.AggregateSelector<T, U, V>(this, seed, accumulator, resultSelector));
5075+
}
5076+
5077+
/**
5078+
* Create an Observable that aggregates the source values with the given indexed accumulator
5079+
* function and projects the final result via the indexed resultselector.
5080+
*
5081+
* @param <U> the intermediate (accumulator) type
5082+
* @param <V> the result type
5083+
* @param seed the initial value of the accumulator
5084+
* @param accumulator the function that takes the current accumulator value,
5085+
* the current emitted value and returns a (new) accumulated value.
5086+
* @param resultSelector the selector to project the final value of the accumulator, where
5087+
* the second argument is the total number of elements accumulated
5088+
* @return an Observable that aggregates the source values with the given indexed accumulator
5089+
* function and projects the final result via the indexed resultselector.
5090+
*/
5091+
public <U, V> Observable<V> aggregateIndexed(
5092+
U seed, Func3<U, ? super T, ? super Integer, U> accumulator,
5093+
Func2<? super U, ? super Integer, ? extends V> resultSelector
5094+
) {
5095+
return create(new OperationAggregate.AggregateIndexedSelector<T, U, V>(this, seed, accumulator, resultSelector));
5096+
}
49575097

49585098
/**
49595099
* Returns an Observable that applies a function of your choosing to the
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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+
17+
package rx.operators;
18+
19+
import rx.Observable;
20+
import rx.Observable.OnSubscribeFunc;
21+
import rx.Observer;
22+
import rx.Subscription;
23+
import rx.util.functions.Func1;
24+
import rx.util.functions.Func2;
25+
import rx.util.functions.Func3;
26+
27+
/**
28+
* Aggregate overloads with index and selector functions.
29+
*/
30+
public final class OperationAggregate {
31+
/** Utility class. */
32+
private OperationAggregate() { throw new IllegalStateException("No instances!"); }
33+
34+
/**
35+
* Aggregate and emit a value after running it through a selector.
36+
* @param <T> the input value type
37+
* @param <U> the intermediate value type
38+
* @param <V> the result value type
39+
*/
40+
public static final class AggregateSelector<T, U, V> implements OnSubscribeFunc<V> {
41+
final Observable<? extends T> source;
42+
final U seed;
43+
final Func2<U, ? super T, U> aggregator;
44+
final Func1<? super U, ? extends V> resultSelector;
45+
46+
public AggregateSelector(
47+
Observable<? extends T> source, U seed,
48+
Func2<U, ? super T, U> aggregator,
49+
Func1<? super U, ? extends V> resultSelector) {
50+
this.source = source;
51+
this.seed = seed;
52+
this.aggregator = aggregator;
53+
this.resultSelector = resultSelector;
54+
}
55+
56+
@Override
57+
public Subscription onSubscribe(Observer<? super V> t1) {
58+
return source.subscribe(new AggregatorObserver(t1, seed));
59+
}
60+
/** The aggregator observer of the source. */
61+
private final class AggregatorObserver implements Observer<T> {
62+
final Observer<? super V> observer;
63+
U accumulator;
64+
public AggregatorObserver(Observer<? super V> observer, U seed) {
65+
this.observer = observer;
66+
this.accumulator = seed;
67+
}
68+
69+
@Override
70+
public void onNext(T args) {
71+
accumulator = aggregator.call(accumulator, args);
72+
}
73+
74+
@Override
75+
public void onError(Throwable e) {
76+
accumulator = null;
77+
observer.onError(e);
78+
}
79+
80+
@Override
81+
public void onCompleted() {
82+
U a = accumulator;
83+
accumulator = null;
84+
try {
85+
observer.onNext(resultSelector.call(a));
86+
} catch (Throwable t) {
87+
observer.onError(t);
88+
return;
89+
}
90+
observer.onCompleted();
91+
}
92+
}
93+
}
94+
/**
95+
* Indexed aggregate and emit a value after running it through an indexed selector.
96+
* @param <T> the input value type
97+
* @param <U> the intermediate value type
98+
* @param <V> the result value type
99+
*/
100+
public static final class AggregateIndexedSelector<T, U, V> implements OnSubscribeFunc<V> {
101+
final Observable<? extends T> source;
102+
final U seed;
103+
final Func3<U, ? super T, ? super Integer, U> aggregator;
104+
final Func2<? super U, ? super Integer, ? extends V> resultSelector;
105+
106+
public AggregateIndexedSelector(
107+
Observable<? extends T> source,
108+
U seed,
109+
Func3<U, ? super T, ? super Integer, U> aggregator,
110+
Func2<? super U, ? super Integer, ? extends V> resultSelector) {
111+
this.source = source;
112+
this.seed = seed;
113+
this.aggregator = aggregator;
114+
this.resultSelector = resultSelector;
115+
}
116+
117+
118+
119+
@Override
120+
public Subscription onSubscribe(Observer<? super V> t1) {
121+
return source.subscribe(new AggregatorObserver(t1, seed));
122+
}
123+
/** The aggregator observer of the source. */
124+
private final class AggregatorObserver implements Observer<T> {
125+
final Observer<? super V> observer;
126+
U accumulator;
127+
int index;
128+
public AggregatorObserver(Observer<? super V> observer, U seed) {
129+
this.observer = observer;
130+
this.accumulator = seed;
131+
}
132+
133+
@Override
134+
public void onNext(T args) {
135+
accumulator = aggregator.call(accumulator, args, index++);
136+
}
137+
138+
@Override
139+
public void onError(Throwable e) {
140+
accumulator = null;
141+
observer.onError(e);
142+
}
143+
144+
@Override
145+
public void onCompleted() {
146+
U a = accumulator;
147+
accumulator = null;
148+
try {
149+
observer.onNext(resultSelector.call(a, index));
150+
} catch (Throwable t) {
151+
observer.onError(t);
152+
return;
153+
}
154+
observer.onCompleted();
155+
}
156+
}
157+
}
158+
}

0 commit comments

Comments
 (0)