All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rx.operators.OperationAverage Maven / Gradle / Ivy

There is a newer version: 0.20.7
Show newest version
/**
 * Copyright 2014 Netflix, Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package rx.operators;

import rx.Observable;
import rx.Observable.OnSubscribeFunc;
import rx.Observer;
import rx.Subscription;
import rx.functions.Func1;
import rx.functions.Func2;

/**
 * A few operators for implementing the averaging operation.
 * 
 * @see MSDN: Observable.Average
 */
public final class OperationAverage {
    private static final class Tuple2 {
        private final T current;
        private final Integer count;

        private Tuple2(T v1, Integer v2) {
            current = v1;
            count = v2;
        }
    }

    public static Observable average(Observable source) {
        return source.reduce(new Tuple2(0, 0), new Func2, Integer, Tuple2>() {
            @Override
            public Tuple2 call(Tuple2 accu, Integer next) {
                return new Tuple2(accu.current + next, accu.count + 1);
            }
        }).map(new Func1, Integer>() {
            @Override
            public Integer call(Tuple2 result) {
                if (result.count == 0) {
                    throw new IllegalArgumentException("Sequence contains no elements");
                }
                return result.current / result.count;
            }
        });
    }

    public static Observable averageLongs(Observable source) {
        return source.reduce(new Tuple2(0L, 0), new Func2, Long, Tuple2>() {
            @Override
            public Tuple2 call(Tuple2 accu, Long next) {
                return new Tuple2(accu.current + next, accu.count + 1);
            }
        }).map(new Func1, Long>() {
            @Override
            public Long call(Tuple2 result) {
                if (result.count == 0) {
                    throw new IllegalArgumentException("Sequence contains no elements");
                }
                return result.current / result.count;
            }
        });
    }

    public static Observable averageFloats(Observable source) {
        return source.reduce(new Tuple2(0.0f, 0), new Func2, Float, Tuple2>() {
            @Override
            public Tuple2 call(Tuple2 accu, Float next) {
                return new Tuple2(accu.current + next, accu.count + 1);
            }
        }).map(new Func1, Float>() {
            @Override
            public Float call(Tuple2 result) {
                if (result.count == 0) {
                    throw new IllegalArgumentException("Sequence contains no elements");
                }
                return result.current / result.count;
            }
        });
    }

    public static Observable averageDoubles(Observable source) {
        return source.reduce(new Tuple2(0.0d, 0), new Func2, Double, Tuple2>() {
            @Override
            public Tuple2 call(Tuple2 accu, Double next) {
                return new Tuple2(accu.current + next, accu.count + 1);
            }
        }).map(new Func1, Double>() {
            @Override
            public Double call(Tuple2 result) {
                if (result.count == 0) {
                    throw new IllegalArgumentException("Sequence contains no elements");
                }
                return result.current / result.count;
            }
        });
    }

    /**
     * Compute the average by extracting integer values from the source via an
     * extractor function.
     * 
     * @param 
     *            the source value type
     */
    public static final class AverageIntegerExtractor implements OnSubscribeFunc {
        final Observable source;
        final Func1 valueExtractor;

        public AverageIntegerExtractor(Observable source, Func1 valueExtractor) {
            this.source = source;
            this.valueExtractor = valueExtractor;
        }

        @Override
        public Subscription onSubscribe(Observer t1) {
            return source.subscribe(new AverageObserver(t1));
        }

        /** Computes the average. */
        private final class AverageObserver implements Observer {
            final Observer observer;
            int sum;
            int count;

            public AverageObserver(Observer observer) {
                this.observer = observer;
            }

            @Override
            public void onNext(T args) {
                sum += valueExtractor.call(args);
                count++;
            }

            @Override
            public void onError(Throwable e) {
                observer.onError(e);
            }

            @Override
            public void onCompleted() {
                if (count > 0) {
                    try {
                        observer.onNext(sum / count);
                    } catch (Throwable t) {
                        observer.onError(t);
                        return;
                    }
                    observer.onCompleted();
                } else {
                    observer.onError(new IllegalArgumentException("Sequence contains no elements"));
                }
            }

        }
    }

    /**
     * Compute the average by extracting long values from the source via an
     * extractor function.
     * 
     * @param 
     *            the source value type
     */
    public static final class AverageLongExtractor implements OnSubscribeFunc {
        final Observable source;
        final Func1 valueExtractor;

        public AverageLongExtractor(Observable source, Func1 valueExtractor) {
            this.source = source;
            this.valueExtractor = valueExtractor;
        }

        @Override
        public Subscription onSubscribe(Observer t1) {
            return source.subscribe(new AverageObserver(t1));
        }

        /** Computes the average. */
        private final class AverageObserver implements Observer {
            final Observer observer;
            long sum;
            int count;

            public AverageObserver(Observer observer) {
                this.observer = observer;
            }

            @Override
            public void onNext(T args) {
                sum += valueExtractor.call(args);
                count++;
            }

            @Override
            public void onError(Throwable e) {
                observer.onError(e);
            }

            @Override
            public void onCompleted() {
                if (count > 0) {
                    try {
                        observer.onNext(sum / count);
                    } catch (Throwable t) {
                        observer.onError(t);
                        return;
                    }
                    observer.onCompleted();
                } else {
                    observer.onError(new IllegalArgumentException("Sequence contains no elements"));
                }
            }

        }
    }

    /**
     * Compute the average by extracting float values from the source via an
     * extractor function.
     * 
     * @param 
     *            the source value type
     */
    public static final class AverageFloatExtractor implements OnSubscribeFunc {
        final Observable source;
        final Func1 valueExtractor;

        public AverageFloatExtractor(Observable source, Func1 valueExtractor) {
            this.source = source;
            this.valueExtractor = valueExtractor;
        }

        @Override
        public Subscription onSubscribe(Observer t1) {
            return source.subscribe(new AverageObserver(t1));
        }

        /** Computes the average. */
        private final class AverageObserver implements Observer {
            final Observer observer;
            float sum;
            int count;

            public AverageObserver(Observer observer) {
                this.observer = observer;
            }

            @Override
            public void onNext(T args) {
                sum += valueExtractor.call(args);
                count++;
            }

            @Override
            public void onError(Throwable e) {
                observer.onError(e);
            }

            @Override
            public void onCompleted() {
                if (count > 0) {
                    try {
                        observer.onNext(sum / count);
                    } catch (Throwable t) {
                        observer.onError(t);
                        return;
                    }
                    observer.onCompleted();
                } else {
                    observer.onError(new IllegalArgumentException("Sequence contains no elements"));
                }
            }

        }
    }

    /**
     * Compute the average by extracting double values from the source via an
     * extractor function.
     * 
     * @param 
     *            the source value type
     */
    public static final class AverageDoubleExtractor implements OnSubscribeFunc {
        final Observable source;
        final Func1 valueExtractor;

        public AverageDoubleExtractor(Observable source, Func1 valueExtractor) {
            this.source = source;
            this.valueExtractor = valueExtractor;
        }

        @Override
        public Subscription onSubscribe(Observer t1) {
            return source.subscribe(new AverageObserver(t1));
        }

        /** Computes the average. */
        private final class AverageObserver implements Observer {
            final Observer observer;
            double sum;
            int count;

            public AverageObserver(Observer observer) {
                this.observer = observer;
            }

            @Override
            public void onNext(T args) {
                sum += valueExtractor.call(args);
                count++;
            }

            @Override
            public void onError(Throwable e) {
                observer.onError(e);
            }

            @Override
            public void onCompleted() {
                if (count > 0) {
                    try {
                        observer.onNext(sum / count);
                    } catch (Throwable t) {
                        observer.onError(t);
                        return;
                    }
                    observer.onCompleted();
                } else {
                    observer.onError(new IllegalArgumentException("Sequence contains no elements"));
                }
            }

        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy