/* * Apache License * Version 2.0, January 2004 * http://www.apache.org/licenses/ * * Copyright 2013 Aurelian Tutuianu * Copyright 2014 Aurelian Tutuianu * Copyright 2015 Aurelian Tutuianu * Copyright 2016 Aurelian Tutuianu * * 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 rapaio.data.stream; import rapaio.data.MappedVar; import rapaio.data.Mapping; import rapaio.data.Var; import rapaio.util.stream.StreamUtil; import java.io.Serializable; import java.util.Comparator; import java.util.Iterator; import java.util.Optional; import java.util.Spliterator; import java.util.function.*; import java.util.stream.*; /** * Stream of variable spots which enrich the standard java streams with some specific * operations. * * @author <a href="mailto:padreati@yahoo.com>Aurelian Tutuianu</a> */ public class VSpots implements Stream<VSpot>, Serializable { private final Stream<VSpot> stream; private final Var source; /** * Builds a stream of variable spots based on a standard java stream of spots * * @param stream nested stream */ public VSpots(Stream<VSpot> stream, Var source) { this.stream = stream; this.source = source; } @Override public VSpots filter(Predicate<? super VSpot> predicate) { return new VSpots(stream.filter(predicate), source); } @Override public <R> Stream<R> map(Function<? super VSpot, ? extends R> mapper) { return stream.map(mapper); } @Override public IntStream mapToInt(ToIntFunction<? super VSpot> mapper) { return stream.mapToInt(mapper); } @Override public LongStream mapToLong(ToLongFunction<? super VSpot> mapper) { return stream.mapToLong(mapper); } @Override public DoubleStream mapToDouble(ToDoubleFunction<? super VSpot> mapper) { return stream.mapToDouble(mapper); } /** * Map the observations to the numerical value given by {@link VSpot#value()} * * @return stream of numerical values */ public DoubleStream mapToDouble() { return mapToDouble(VSpot::value); } /** * Map the observations to the index value given by {@link VSpot#index()} * * @return stream of integer values */ public IntStream mapToInt() { return mapToInt(VSpot::index); } /** * Map the observations to the label value given by {@link VSpot#label()} * * @return stream of label values */ public Stream<String> mapToString() { return map(VSpot::label); } @Override public <R> Stream<R> flatMap(Function<? super VSpot, ? extends Stream<? extends R>> mapper) { return stream.flatMap(mapper); } @Override public IntStream flatMapToInt(Function<? super VSpot, ? extends IntStream> mapper) { return stream.flatMapToInt(mapper); } @Override public LongStream flatMapToLong(Function<? super VSpot, ? extends LongStream> mapper) { return stream.flatMapToLong(mapper); } @Override public DoubleStream flatMapToDouble(Function<? super VSpot, ? extends DoubleStream> mapper) { return stream.flatMapToDouble(mapper); } @Override public VSpots distinct() { return new VSpots(stream.distinct(), source); } @Override public VSpots sorted() { return new VSpots(stream.sorted(), source); } @Override public VSpots sorted(Comparator<? super VSpot> comparator) { return new VSpots(stream.sorted(comparator), source); } @Override public VSpots peek(Consumer<? super VSpot> action) { return new VSpots(stream.peek(action), source); } @Override public VSpots limit(long maxSize) { return new VSpots(stream.limit(maxSize), source); } @Override public VSpots skip(long n) { return new VSpots(stream.skip(n), source); } @Override public void forEach(Consumer<? super VSpot> action) { stream.forEach(action); } @Override public void forEachOrdered(Consumer<? super VSpot> action) { stream.forEachOrdered(action); } @Override public Object[] toArray() { return stream.toArray(); } @Override public <A> A[] toArray(IntFunction<A[]> generator) { return stream.toArray(generator); } @Override public VSpot reduce(VSpot identity, BinaryOperator<VSpot> accumulator) { return stream.reduce(identity, accumulator, accumulator); } @Override public Optional<VSpot> reduce(BinaryOperator<VSpot> accumulator) { return stream.reduce(accumulator); } @Override public <U> U reduce(U identity, BiFunction<U, ? super VSpot, U> accumulator, BinaryOperator<U> combiner) { return stream.reduce(identity, accumulator, combiner); } @Override public <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super VSpot> accumulator, BiConsumer<R, R> combiner) { return stream.collect(supplier, accumulator, combiner); } @Override public <R, A> R collect(Collector<? super VSpot, A, R> collector) { return stream.collect(collector); } @Override public Optional<VSpot> min(Comparator<? super VSpot> comparator) { return stream.min(comparator); } @Override public Optional<VSpot> max(Comparator<? super VSpot> comparator) { return stream.max(comparator); } @Override public long count() { return stream.count(); } @Override public boolean anyMatch(Predicate<? super VSpot> predicate) { return stream.anyMatch(predicate); } @Override public boolean allMatch(Predicate<? super VSpot> predicate) { return stream.allMatch(predicate); } @Override public boolean noneMatch(Predicate<? super VSpot> predicate) { return stream.noneMatch(predicate); } @Override public Optional<VSpot> findFirst() { return stream.findFirst(); } @Override public Optional<VSpot> findAny() { return stream.findAny(); } @Override public Iterator<VSpot> iterator() { return stream.iterator(); } @Override public Spliterator<VSpot> spliterator() { return stream.spliterator(); } @Override public boolean isParallel() { return stream.isParallel(); } @Override public VSpots sequential() { return new VSpots(stream.sequential(), source); } @Override public VSpots parallel() { return new VSpots(stream.parallel(), source); } @Override public VSpots unordered() { return new VSpots(stream.unordered(), source); } @Override public VSpots onClose(Runnable closeHandler) { return new VSpots(stream.onClose(closeHandler), source); } @Override public void close() { stream.close(); } /** * Filters the spot stream by removing all spots which contains missing values * * @return stream with complete spots */ public VSpots complete() { return new VSpots(stream.filter(s -> !s.missing()), source); } /** * Filters the spot stream by removing all spots which does not contain missing values * * @return stream with spots with missing values */ public VSpots incomplete() { return new VSpots(stream.filter(VSpot::missing), source); } /** * Builds a stream of spot streams, each stream having the size given by {@param groupSize} * * @param groupSize the size of the groups which forms each stream * @return a stream of streams */ public Stream<VSpots> group(int groupSize) { return StreamUtil.partition(stream, groupSize).map(list -> new VSpots(list.stream(), source)); } /** * Makes a string which contains a concatenation of mapped values * * @param mapper mapper used to transform a spot into a specific value * @return a string made from the concatenation of mapped values */ public <R> String mkString(Function<VSpot, R> mapper) { StringBuilder sb = new StringBuilder(); Iterator<R> it = stream.map(mapper).iterator(); while (it.hasNext()) { if (sb.length() != 0) sb.append(","); sb.append(it.next().toString()); } return "[" + sb.toString() + "]"; } /** * Applies a given transformation to all the numerical values of the underlying variable * * @param trans given transformation */ public VSpots transValue(Function<Double, Double> trans) { return new VSpots(stream.map(spot -> { spot.setValue(trans.apply(spot.value())); return spot; }), source); } /** * Applies a given transformation to all index values of the underlying variable * * @param trans given transformation */ public VSpots transIndex(Function<Integer, Integer> trans) { return new VSpots(stream.map(spot -> { spot.setIndex(trans.apply(spot.index())); return spot; }), source); } /** * Applies a given transformation to all label values of the underlying variable * * @param trans given transformation */ public VSpots transLabel(Function<String, String> trans) { return new VSpots(stream.map(spot -> { spot.setLabel(trans.apply(spot.label())); return spot; }), source); } /** * Builds a mapped variable which contains all the observations from the stream. * This is a terminal operation. * * @return new mapped variable */ public MappedVar toMappedVar() { return MappedVar.byRows(source, Mapping.wrap(stream.map(VSpot::row).collect(Collectors.toList()))); } }