/** * Returns a {@link BitSet} containing the elements of this stream. * * <p> * This is a terminal operation. * * @return a {@code BitSet} which set bits correspond to the elements of * this stream. * @since 0.2.0 */ public BitSet toBitSet() { return collect(BitSet::new, BitSet::set, BitSet::or); }
@Override public IntSummaryStatistics summaryStatistics() { return collect(IntSummaryStatistics::new, IntSummaryStatistics::accept, IntSummaryStatistics::combine); }
/** * Returns a {@link String} consisting of code points from this stream. * * <p> * This is a terminal operation. * * @return a new {@code String} * @since 0.2.1 */ public String codePointsToString() { return collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString(); }
/** * Returns a {@link String} consisting of chars from this stream. * * <p> * This is a terminal operation. * * <p> * During string creation stream elements are converted to chars using * {@code (char)} cast operation. * * @return a new {@code String} * @since 0.2.1 */ public String charsToString() { return collect(StringBuilder::new, (sb, c) -> sb.append((char) c), StringBuilder::append).toString(); }
/** * Returns a {@link String} which is the concatenation of the results of * calling {@link String#valueOf(int)} on each element of this stream, * separated by the specified delimiter, in encounter order. * * <p> * This is a terminal operation. * * @param delimiter the delimiter to be used between each element * @return the result of concatenation. For empty input stream empty String * is returned. * @since 0.3.1 */ public String joining(CharSequence delimiter) { return collect(IntCollector.joining(delimiter)); }
/** * Returns a {@link String} which is the concatenation of the results of * calling {@link String#valueOf(int)} on each element of this stream, * separated by the specified delimiter, with the specified prefix and * suffix in encounter order. * * <p> * This is a terminal operation. * * @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 the result of concatenation. For empty input stream * {@code prefix + suffix} is returned. * @since 0.3.1 */ public String joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) { return collect(IntCollector.joining(delimiter, prefix, suffix)); }
/** * Returns the minimum element of this stream according to the provided key * extractor function. * * <p> * This is a terminal operation. * * @param keyExtractor a non-interfering, stateless function * @return an {@code OptionalInt} describing the first element of this * stream for which the lowest value was returned by key extractor, * or an empty {@code OptionalInt} if the stream is empty * @since 0.1.2 */ public OptionalInt minByInt(IntUnaryOperator keyExtractor) { int[] result = collect(() -> new int[3], (acc, i) -> { int key = keyExtractor.applyAsInt(i); if (acc[2] == 0 || acc[1] > key) { acc[0] = i; acc[1] = key; acc[2] = 1; } }, (acc1, acc2) -> { if (acc2[2] == 1 && (acc1[2] == 0 || acc1[1] > acc2[1])) System.arraycopy(acc2, 0, acc1, 0, 3); }); return result[2] == 1 ? OptionalInt.of(result[0]) : OptionalInt.empty(); }
/** * Returns the maximum element of this stream according to the provided key * extractor function. * * <p> * This is a terminal operation. * * @param keyExtractor a non-interfering, stateless function * @return an {@code OptionalInt} describing the first element of this * stream for which the highest value was returned by key extractor, * or an empty {@code OptionalInt} if the stream is empty * @since 0.1.2 */ public OptionalInt maxByInt(IntUnaryOperator keyExtractor) { int[] result = collect(() -> new int[3], (acc, i) -> { int key = keyExtractor.applyAsInt(i); if (acc[2] == 0 || acc[1] < key) { acc[0] = i; acc[1] = key; acc[2] = 1; } }, (acc1, acc2) -> { if (acc2[2] == 1 && (acc1[2] == 0 || acc1[1] < acc2[1])) System.arraycopy(acc2, 0, acc1, 0, 3); }); return result[2] == 1 ? OptionalInt.of(result[0]) : OptionalInt.empty(); }
/** * Returns the minimum element of this stream according to the provided key * extractor function. * * <p> * This is a terminal operation. * * @param <V> the type of the {@code Comparable} sort key * @param keyExtractor a non-interfering, stateless function * @return an {@code OptionalInt} describing some element of this stream for * which the lowest value was returned by key extractor, or an empty * {@code OptionalInt} if the stream is empty * @since 0.1.2 */ public <V extends Comparable<? super V>> OptionalInt minBy(IntFunction<V> keyExtractor) { ObjIntBox<V> result = collect(() -> new ObjIntBox<>(null, 0), (box, i) -> { V val = Objects.requireNonNull(keyExtractor.apply(i)); if (box.a == null || box.a.compareTo(val) > 0) { box.a = val; box.b = i; } }, (box1, box2) -> { if (box2.a != null && (box1.a == null || box1.a.compareTo(box2.a) > 0)) { box1.a = box2.a; box1.b = box2.b; } }); return result.a == null ? OptionalInt.empty() : OptionalInt.of(result.b); }
/** * Returns the maximum element of this stream according to the provided key * extractor function. * * <p> * This is a terminal operation. * * @param <V> the type of the {@code Comparable} sort key * @param keyExtractor a non-interfering, stateless function * @return an {@code OptionalInt} describing the first element of this * stream for which the highest value was returned by key extractor, * or an empty {@code OptionalInt} if the stream is empty * @since 0.1.2 */ public <V extends Comparable<? super V>> OptionalInt maxBy(IntFunction<V> keyExtractor) { ObjIntBox<V> result = collect(() -> new ObjIntBox<>(null, 0), (box, i) -> { V val = Objects.requireNonNull(keyExtractor.apply(i)); if (box.a == null || box.a.compareTo(val) < 0) { box.a = val; box.b = i; } }, (box1, box2) -> { if (box2.a != null && (box1.a == null || box1.a.compareTo(box2.a) < 0)) { box1.a = box2.a; box1.b = box2.b; } }); return result.a == null ? OptionalInt.empty() : OptionalInt.of(result.b); }
/** * Returns the maximum element of this stream according to the provided key * extractor function. * * <p> * This is a terminal operation. * * @param keyExtractor a non-interfering, stateless function * @return an {@code OptionalInt} describing the first element of this * stream for which the highest value was returned by key extractor, * or an empty {@code OptionalInt} if the stream is empty * @since 0.1.2 */ public OptionalInt maxByDouble(IntToDoubleFunction keyExtractor) { return collect(PrimitiveBox::new, (box, i) -> { double key = keyExtractor.applyAsDouble(i); if (!box.b || Double.compare(box.d, key) < 0) { box.b = true; box.d = key; box.i = i; } }, PrimitiveBox.MAX_DOUBLE).asInt(); }
/** * Returns the minimum element of this stream according to the provided key * extractor function. * * <p> * This is a terminal operation. * * @param keyExtractor a non-interfering, stateless function * @return an {@code OptionalInt} describing some element of this stream for * which the lowest value was returned by key extractor, or an empty * {@code OptionalInt} if the stream is empty * @since 0.1.2 */ public OptionalInt minByDouble(IntToDoubleFunction keyExtractor) { return collect(PrimitiveBox::new, (box, i) -> { double key = keyExtractor.applyAsDouble(i); if (!box.b || Double.compare(box.d, key) > 0) { box.b = true; box.d = key; box.i = i; } }, PrimitiveBox.MIN_DOUBLE).asInt(); }
/** * Returns the maximum element of this stream according to the provided key * extractor function. * * <p> * This is a terminal operation. * * @param keyExtractor a non-interfering, stateless function * @return an {@code OptionalInt} describing the first element of this * stream for which the highest value was returned by key extractor, * or an empty {@code OptionalInt} if the stream is empty * @since 0.1.2 */ public OptionalInt maxByLong(IntToLongFunction keyExtractor) { return collect(PrimitiveBox::new, (box, i) -> { long key = keyExtractor.applyAsLong(i); if (!box.b || box.l < key) { box.b = true; box.l = key; box.i = i; } }, PrimitiveBox.MAX_LONG).asInt(); }
/** * Returns the minimum element of this stream according to the provided key * extractor function. * * <p> * This is a terminal operation. * * @param keyExtractor a non-interfering, stateless function * @return an {@code OptionalInt} describing some element of this stream for * which the lowest value was returned by key extractor, or an empty * {@code OptionalInt} if the stream is empty * @since 0.1.2 */ public OptionalInt minByLong(IntToLongFunction keyExtractor) { return collect(PrimitiveBox::new, (box, i) -> { long key = keyExtractor.applyAsLong(i); if (!box.b || box.l > key) { box.b = true; box.l = key; box.i = i; } }, PrimitiveBox.MIN_LONG).asInt(); }
/** * Performs a mutable reduction operation on the elements of this stream * using an {@link IntCollector} which encapsulates the supplier, * accumulator and merger functions making easier to reuse collection * strategies. * * <p> * Like {@link #reduce(int, IntBinaryOperator)}, {@code collect} operations * can be parallelized without requiring additional synchronization. * * <p> * This is a terminal operation. * * @param <A> the intermediate accumulation type of the {@code IntCollector} * @param <R> type of the result * @param collector the {@code IntCollector} describing the reduction * @return the result of the reduction * @see #collect(Supplier, ObjIntConsumer, BiConsumer) * @since 0.3.0 */ @SuppressWarnings("unchecked") public <A, R> R collect(IntCollector<A, R> collector) { if (collector.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) return (R) collect(collector.supplier(), collector.intAccumulator(), collector.merger()); return collector.finisher().apply(collect(collector.supplier(), collector.intAccumulator(), collector .merger())); }
private <A> A collectSized(Supplier<A> supplier, ObjIntConsumer<A> accumulator, BiConsumer<A, A> combiner, IntFunction<A> sizedSupplier, ObjIntConsumer<A> sizedAccumulator) { if (isParallel()) return collect(supplier, accumulator, combiner); java.util.Spliterator.OfInt spliterator = spliterator(); long size = spliterator.getExactSizeIfKnown(); A intermediate; if (size >= 0 && size <= Integer.MAX_VALUE) { intermediate = sizedSupplier.apply((int) size); spliterator.forEachRemaining((IntConsumer) i -> sizedAccumulator.accept(intermediate, i)); } else { intermediate = supplier.get(); spliterator.forEachRemaining((IntConsumer) i -> accumulator.accept(intermediate, i)); } return intermediate; }