@SuppressWarnings({ "unchecked", "rawtypes" }) static <A, R> PartialCollector<BooleanMap<A>, Map<Boolean, R>> partialCollector(Collector<?, A, R> downstream) { Supplier<A> downstreamSupplier = downstream.supplier(); Supplier<BooleanMap<A>> supplier = () -> new BooleanMap<>(downstreamSupplier.get(), downstreamSupplier .get()); BinaryOperator<A> downstreamCombiner = downstream.combiner(); BiConsumer<BooleanMap<A>, BooleanMap<A>> merger = (left, right) -> { left.trueValue = downstreamCombiner.apply(left.trueValue, right.trueValue); left.falseValue = downstreamCombiner.apply(left.falseValue, right.falseValue); }; if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { return (PartialCollector) new PartialCollector<>(supplier, merger, Function.identity(), ID_CHARACTERISTICS); } Function<A, R> downstreamFinisher = downstream.finisher(); return new PartialCollector<>(supplier, merger, par -> new BooleanMap<>(downstreamFinisher .apply(par.trueValue), downstreamFinisher.apply(par.falseValue)), NO_CHARACTERISTICS); } }
downstreamAccumulator.accept(container, t); }; PartialCollector<Map<K, A>, M> partial = PartialCollector.grouping(mapFactory, downstream); Predicate<A> downstreamFinished = finished(downstream); if (downstreamFinished != null) { int size = domain.size(); groupingBy = partial.asCancellable(accumulator, map -> { if (map.size() < size) return false; }); } else { groupingBy = partial.asRef(accumulator);
if (finished != null) { BiConsumer<A, ? super T> accumulator = downstream.accumulator(); return BooleanMap.partialCollector(downstream).asCancellable((map, t) -> accumulator.accept(predicate.test( t) ? map.trueValue : map.falseValue, t), map -> finished.test(map.trueValue) && finished.test( map.falseValue));
/** * Returns a {@code LongCollector} which partitions the input numbers * according to a {@code LongPredicate}, reduces the values in each * partition according to another {@code IntCollector}, and organizes them * into a {@code Map<Boolean, D>} whose values are the result of the * downstream reduction. * * <p> * There are no guarantees on the type, mutability, serializability, or * thread-safety of the {@code Map} returned. * * @param <A> the intermediate accumulation type of the downstream collector * @param <D> the result type of the downstream reduction * @param predicate a predicate used for classifying input elements * @param downstream a {@code LongCollector} implementing the downstream * reduction * @return a {@code LongCollector} implementing the cascaded partitioning * operation */ static <A, D> LongCollector<?, Map<Boolean, D>> partitioningBy(LongPredicate predicate, LongCollector<A, D> downstream) { ObjLongConsumer<A> downstreamAccumulator = downstream.longAccumulator(); ObjLongConsumer<BooleanMap<A>> accumulator = (result, t) -> downstreamAccumulator.accept( predicate.test(t) ? result.trueValue : result.falseValue, t); return BooleanMap.partialCollector(downstream).asLong(accumulator); }
/** * Returns a {@code DoubleCollector} which partitions the input numbers * according to a {@code DoublePredicate}, reduces the values in each * partition according to another {@code IntCollector}, and organizes them * into a {@code Map<Boolean, D>} whose values are the result of the * downstream reduction. * * <p> * There are no guarantees on the type, mutability, serializability, or * thread-safety of the {@code Map} returned. * * @param <A> the intermediate accumulation type of the downstream collector * @param <D> the result type of the downstream reduction * @param predicate a predicate used for classifying input elements * @param downstream a {@code DoubleCollector} implementing the downstream * reduction * @return a {@code DoubleCollector} implementing the cascaded partitioning * operation */ static <A, D> DoubleCollector<?, Map<Boolean, D>> partitioningBy(DoublePredicate predicate, DoubleCollector<A, D> downstream) { ObjDoubleConsumer<A> downstreamAccumulator = downstream.doubleAccumulator(); ObjDoubleConsumer<BooleanMap<A>> accumulator = (result, t) -> downstreamAccumulator.accept( predicate.test(t) ? result.trueValue : result.falseValue, t); return BooleanMap.partialCollector(downstream).asDouble(accumulator); }
/** * Adapts a {@link Collector} accepting elements of type {@code U} to an * {@code IntCollector} by applying a mapping function to each input element * before accumulation. * * @param <U> type of elements accepted by downstream collector * @param <A> intermediate accumulation type of the downstream collector * @param <R> result type of collector * @param mapper a function to be applied to the input elements * @param downstream a collector which will accept mapped values * @return a collector which applies the mapping function to the input * elements and provides the mapped results to the downstream * collector */ static <U, A, R> IntCollector<?, R> mappingToObj(IntFunction<U> mapper, Collector<U, A, R> downstream) { BiConsumer<A, U> accumulator = downstream.accumulator(); if (downstream instanceof MergingCollector) { return new IntCollectorImpl<>(downstream.supplier(), (acc, i) -> accumulator.accept(acc, mapper.apply(i)), ((MergingCollector<U, A, R>) downstream).merger(), downstream.finisher(), downstream .characteristics()); } return Box.partialCollector(downstream).asInt((box, i) -> accumulator.accept(box.a, mapper.apply(i))); }
/** * Adapts a {@link Collector} accepting elements of type {@code U} to a * {@code LongCollector} by applying a mapping function to each input * element before accumulation. * * @param <U> type of elements accepted by downstream collector * @param <A> intermediate accumulation type of the downstream collector * @param <R> result type of collector * @param mapper a function to be applied to the input elements * @param downstream a collector which will accept mapped values * @return a collector which applies the mapping function to the input * elements and provides the mapped results to the downstream * collector */ static <U, A, R> LongCollector<?, R> mappingToObj(LongFunction<U> mapper, Collector<U, A, R> downstream) { BiConsumer<A, U> accumulator = downstream.accumulator(); if (downstream instanceof MergingCollector) { return new LongCollectorImpl<>(downstream.supplier(), (acc, i) -> accumulator.accept(acc, mapper.apply(i)), ((MergingCollector<U, A, R>) downstream).merger(), downstream.finisher(), downstream .characteristics()); } return Box.partialCollector(downstream).asLong((box, i) -> accumulator.accept(box.a, mapper.apply(i))); }
/** * Adapts a {@link Collector} accepting elements of type {@code U} to a * {@code DoubleCollector} by applying a mapping function to each input * element before accumulation. * * @param <U> type of elements accepted by downstream collector * @param <A> intermediate accumulation type of the downstream collector * @param <R> result type of collector * @param mapper a function to be applied to the input elements * @param downstream a collector which will accept mapped values * @return a collector which applies the mapping function to the input * elements and provides the mapped results to the downstream * collector */ static <U, A, R> DoubleCollector<?, R> mappingToObj(DoubleFunction<U> mapper, Collector<U, A, R> downstream) { BiConsumer<A, U> accumulator = downstream.accumulator(); if (downstream instanceof MergingCollector) { return new DoubleCollectorImpl<>(downstream.supplier(), (acc, i) -> accumulator .accept(acc, mapper.apply(i)), ((MergingCollector<U, A, R>) downstream).merger(), downstream .finisher(), downstream.characteristics()); } return Box.partialCollector(downstream).asDouble((box, i) -> accumulator.accept(box.a, mapper.apply(i))); }
/** * Returns an {@code IntCollector} which partitions the input numbers * according to an {@code IntPredicate}, reduces the values in each * partition according to another {@code IntCollector}, and organizes them * into a {@code Map<Boolean, D>} whose values are the result of the * downstream reduction. * * <p> * There are no guarantees on the type, mutability, serializability, or * thread-safety of the {@code Map} returned. * * @param <A> the intermediate accumulation type of the downstream collector * @param <D> the result type of the downstream reduction * @param predicate a predicate used for classifying input elements * @param downstream an {@code IntCollector} implementing the downstream * reduction * @return an {@code IntCollector} implementing the cascaded partitioning * operation */ static <A, D> IntCollector<?, Map<Boolean, D>> partitioningBy(IntPredicate predicate, IntCollector<A, D> downstream) { ObjIntConsumer<A> downstreamAccumulator = downstream.intAccumulator(); ObjIntConsumer<BooleanMap<A>> accumulator = (result, t) -> downstreamAccumulator.accept( predicate.test(t) ? result.trueValue : result.falseValue, t); return BooleanMap.partialCollector(downstream).asInt(accumulator); }
/** * Returns an {@code IntCollector} which produces a boolean array containing * the results of applying the given predicate to the input elements, in * encounter order. * * @param predicate a non-interfering, stateless predicate to apply to each * input element. The result values of this predicate are collected * to the resulting boolean array. * @return an {@code IntCollector} which collects the results of the * predicate function to the boolean array, in encounter order. * @since 0.3.8 */ static IntCollector<?, boolean[]> toBooleanArray(IntPredicate predicate) { return PartialCollector.booleanArray().asInt((box, t) -> { if (predicate.test(t)) box.a.set(box.b); box.b = StrictMath.addExact(box.b, 1); }); } }
/** * Returns a {@code LongCollector} which produces a boolean array containing * the results of applying the given predicate to the input elements, in * encounter order. * * @param predicate a non-interfering, stateless predicate to apply to each * input element. The result values of this predicate are collected * to the resulting boolean array. * @return a {@code LongCollector} which collects the results of the * predicate function to the boolean array, in encounter order. * @since 0.3.8 */ static LongCollector<?, boolean[]> toBooleanArray(LongPredicate predicate) { return PartialCollector.booleanArray().asLong((box, t) -> { if (predicate.test(t)) box.a.set(box.b); box.b = StrictMath.addExact(box.b, 1); }); } }
/** * Returns a {@code DoubleCollector} which produces a boolean array * containing the results of applying the given predicate to the input * elements, in encounter order. * * @param predicate a non-interfering, stateless predicate to apply to each * input element. The result values of this predicate are collected * to the resulting boolean array. * @return a {@code DoubleCollector} which collects the results of the * predicate function to the boolean array, in encounter order. * @since 0.3.8 */ static DoubleCollector<?, boolean[]> toBooleanArray(DoublePredicate predicate) { return PartialCollector.booleanArray().asDouble((box, t) -> { if (predicate.test(t)) box.a.set(box.b); box.b = StrictMath.addExact(box.b, 1); }); } }
/** * Returns a {@code LongCollector} that converts the input numbers to * strings and concatenates them, separated by the specified delimiter, with * the specified prefix and suffix, in encounter order. * * @param delimiter the delimiter to be used between each element * @param prefix the sequence of characters to be used at the beginning of * the joined result * @param suffix the sequence of characters to be used at the end of the * joined result * @return A {@code LongCollector} which concatenates the input numbers, * separated by the specified delimiter, in encounter order */ static LongCollector<?, String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) { return PartialCollector.joining(delimiter, prefix, suffix, true).asLong( StreamExInternals.joinAccumulatorLong(delimiter)); }
/** * Returns a {@code DoubleCollector} that converts the input numbers to * strings and concatenates them, separated by the specified delimiter, with * the specified prefix and suffix, in encounter order. * * @param delimiter the delimiter to be used between each element * @param prefix the sequence of characters to be used at the beginning of * the joined result * @param suffix the sequence of characters to be used at the end of the * joined result * @return A {@code DoubleCollector} which concatenates the input numbers, * separated by the specified delimiter, in encounter order */ static DoubleCollector<?, String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) { return PartialCollector.joining(delimiter, prefix, suffix, true).asDouble( StreamExInternals.joinAccumulatorDouble(delimiter)); }
@SuppressWarnings("unchecked") static <K, D, A, M extends Map<K, D>> PartialCollector<Map<K, A>, M> grouping(Supplier<M> mapFactory, Collector<?, A, D> downstream) { BinaryOperator<A> downstreamMerger = downstream.combiner(); BiConsumer<Map<K, A>, Map<K, A>> merger = (map1, map2) -> { for (Map.Entry<K, A> e : map2.entrySet()) map1.merge(e.getKey(), e.getValue(), downstreamMerger); }; if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { return (PartialCollector<Map<K, A>, M>) new PartialCollector<>((Supplier<Map<K, A>>) mapFactory, merger, Function.identity(), ID_CHARACTERISTICS); } Function<A, D> downstreamFinisher = downstream.finisher(); return new PartialCollector<>((Supplier<Map<K, A>>) mapFactory, merger, map -> { map.replaceAll((k, v) -> ((Function<A, A>) downstreamFinisher).apply(v)); return (M) map; }, NO_CHARACTERISTICS); }
static PartialCollector<StringBuilder, String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix, boolean hasPS) { BiConsumer<StringBuilder, StringBuilder> merger = (sb1, sb2) -> { if (sb2.length() > 0) { if (sb1.length() > 0) sb1.append(delimiter); sb1.append(sb2); } }; Supplier<StringBuilder> supplier = StringBuilder::new; if (hasPS) return new PartialCollector<>(supplier, merger, sb -> String.valueOf(prefix) + sb + suffix, NO_CHARACTERISTICS); return new PartialCollector<>(supplier, merger, StringBuilder::toString, NO_CHARACTERISTICS); } }
/** * Returns a {@code Collector} which produces a boolean array containing the * results of applying the given predicate to the input elements, in * encounter order. * * @param <T> the type of the input elements * @param predicate a non-interfering, stateless predicate to apply to each * input element. The result values of this predicate are collected * to the resulting boolean array. * @return a {@code Collector} which collects the results of the predicate * function to the boolean array, in encounter order. * @since 0.3.8 */ public static <T> Collector<T, ?, boolean[]> toBooleanArray(Predicate<T> predicate) { return PartialCollector.booleanArray().asRef((box, t) -> { if (predicate.test(t)) box.a.set(box.b); box.b = StrictMath.addExact(box.b, 1); }); }