void clear() { other = null; payload = none(); } }
CollapseSpliterator(BiPredicate<? super T, ? super T> mergeable, Function<T, R> mapper, BiFunction<R, T, R> accumulator, BinaryOperator<R> combiner, Spliterator<T> source) { super(none()); this.source = source; this.mergeable = mergeable; this.mapper = mapper; this.accumulator = accumulator; this.combiner = combiner; this.root = this; }
private CollapseSpliterator(CollapseSpliterator<T, R> root, Spliterator<T> source, Connector<T, R> left, Connector<T, R> right) { super(none()); this.source = source; this.root = root; this.mergeable = root.mergeable; this.mapper = root.mapper; this.accumulator = root.accumulator; this.combiner = root.combiner; this.left = left; this.right = right; if (left != null) left.rhs = this; right.lhs = this; }
R drainRight() { return right == NONE ? drain() : none(); } }
R drainLeft() { return left == NONE ? drain() : none(); }
@Override public Spliterator<T> trySplit() { if(acc != NONE) { return null; } @SuppressWarnings("unchecked") S prefix = (S) source.trySplit(); if(prefix == null) { return null; } if(accRef == null) { accRef = new AtomicReference<>(none()); } PrefixOps<T, S> pref = doClone(); pref.source = prefix; return pref; }
private R pushLeft(T first, R acc) { synchronized (root) { Connector<T, R> l = left; if (l == null) return acc; left = null; l.rhs = null; T laright = l.right; l.right = none(); if (l.acc == NONE) { l.acc = acc; l.left = first; return none(); } if (this.mergeable.test(laright, first)) { l.acc = this.combiner.apply(l.acc, acc); return l.drainLeft(); } if (l.left == NONE) { left = new Connector<>(null, acc, this); return l.drain(); } } return acc; }
Connector<T, R> l = left, r = right; if (l == null) { return pushRight(none(), none()); l.right = none(); if (l.acc == NONE) { if (r == null) return none(); l.right = laright; return none(); r.left = none(); if (mergeable.test(laright, raleft)) { R acc = combiner.apply(l.acc, r.acc); l.rhs = r.rhs; return none();
@Override public void forEachRemaining(Consumer<? super R> action) { while (left != null) { accept(handleLeft(), action); } if (a != NONE) { acc = mapper.apply(a); } source.forEachRemaining(next -> { if (a == NONE) { acc = mapper.apply(next); } else if (!this.mergeable.test(a, next)) { action.accept(acc); acc = mapper.apply(next); } else { acc = accumulator.apply(acc, next); } a = next; }); if (a == NONE) { accept(pushRight(none(), none()), action); } else if (accept(pushRight(acc, a), action)) { if (right != null) { action.accept(right.acc); right = null; } } }
@Override public Spliterator<R> trySplit() { Spliterator<T> prefix = source.trySplit(); if (prefix == null) return null; Connector<T, R> newBox = new Connector<>(null, none(), this); synchronized (root) { CollapseSpliterator<T, R> result = new CollapseSpliterator<>(root, prefix, left, newBox); this.left = newBox; return result; } }
/** * Returns a {@code Collector} which collects only the first stream element * if any. * * <p> * This method returns a * <a href="package-summary.html#ShortCircuitReduction">short-circuiting * collector</a>. * * <p> * The operation performed by the returned collector is equivalent to * {@code stream.findFirst()}. This collector is mostly useful as a * downstream collector. * * @param <T> the type of the input elements * @return a collector which returns an {@link Optional} which describes the * first element of the stream. For empty stream an empty * {@code Optional} is returned. */ public static <T> Collector<T, ?, Optional<T>> first() { return new CancellableCollectorImpl<>(() -> new Box<T>(none()), (box, t) -> { if (box.a == NONE) box.a = t; }, (box1, box2) -> box1.a == NONE ? box2 : box1, box -> box.a == NONE ? Optional.empty() : Optional.of(box.a), box -> box.a != NONE, NO_CHARACTERISTICS); }
return empty(); if (n == 1) { return Collector.of(() -> new Box<T>(none()), (box, t) -> { if (box.a == NONE || comparator.compare(t, box.a) < 0) box.a = t;
private R handleLeft() { synchronized (root) { Connector<T, R> l = left; if (l == null) { return none(); } if (l.left == NONE && l.right == NONE && l.acc != NONE) { return l.drain(); } } if (source.tryAdvance(this)) { T first = this.a; T last = first; R acc = this.mapper.apply(first); while (source.tryAdvance(this)) { if (!this.mergeable.test(last, a)) return pushLeft(first, acc); last = a; acc = this.accumulator.apply(acc, last); } a = none(); return connectOne(first, acc, last); } return connectEmpty(); }
@Override public boolean tryAdvance(Consumer<? super R> action) { if (left != null) { if (accept(handleLeft(), action)) { return true; } } if (a == NONE) {// start if (!source.tryAdvance(this)) { return accept(pushRight(none(), none()), action); } } T first = a; R acc = mapper.apply(a); T last = first; while (source.tryAdvance(this)) { if (!this.mergeable.test(last, a)) { action.accept(acc); return true; } last = a; acc = this.accumulator.apply(acc, last); } return accept(pushRight(acc, last), action); }
Box<T> result = new Box<>(none()); forEachOrdered(t -> result.a = result.a == NONE ? t : accumulator.apply(result.a, t)); return result.a == NONE ? Optional.empty() : Optional.of(result.a);
BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator(); BinaryOperator<A> downstreamCombiner = downstream.combiner(); Supplier<PairBox<A, T>> supplier = () -> new PairBox<>(downstreamSupplier.get(), none()); BiConsumer<PairBox<A, T>, T> accumulator = (acc, t) -> { if (acc.b == NONE) {
private R connectOne(T first, R acc, T last) { synchronized (root) { Connector<T, R> l = left; if (l == null) { return pushRight(acc, last); } if (l.acc == NONE) { l.acc = acc; l.left = first; l.right = last; return connectEmpty(); } T laright = l.right; if (mergeable.test(laright, first)) { l.acc = combiner.apply(l.acc, acc); l.right = last; return connectEmpty(); } left = null; l.rhs = null; l.right = none(); if (l.left != NONE) { return pushRight(acc, last); } acc = pushRight(acc, last); if (acc != NONE) left = new Connector<>(null, acc, this); return l.drain(); } }