s = source;
77 | element = null;
78 | mode = 0;
79 | source = null;
80 | return s;
81 | }
82 |
83 | @Override
84 | public Spliterator trySplit() {
85 | if (mode == 0)
86 | return source.trySplit();
87 | mode = 0;
88 | return new ConstSpliterator.OfRef<>(element, 1, true);
89 | }
90 |
91 | @Override
92 | public long estimateSize() {
93 | long size = source.estimateSize();
94 | return mode == 0 || size == Long.MAX_VALUE ? size : size + 1;
95 | }
96 |
97 | @Override
98 | public int characteristics() {
99 | switch (mode) {
100 | case 1:
101 | return source.characteristics() & (ORDERED | SIZED | SUBSIZED);
102 | case 2:
103 | return source.characteristics() & ORDERED;
104 | default:
105 | return source.characteristics();
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/main/java/one/util/streamex/StreamContext.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import java.util.concurrent.ForkJoinPool;
19 | import java.util.function.Function;
20 | import java.util.function.Supplier;
21 | import java.util.stream.BaseStream;
22 |
23 | /**
24 | * This class controls stream execution mode (parallel/sequential), custom FJP
25 | * and close handlers.
26 | *
27 | *
28 | * Fields are package-private and mutable, but it's forbidden to change them
29 | * from outside this class.
30 | *
31 | *
32 | * For performance reasons shared objects SEQUENTIAL and PARALLEL are used: then
33 | * have no custom FJP and no close handler. If custom FJP or close handler is
34 | * requested for shared object, a new object is created, otherwise the current
35 | * one is modified.
36 | *
37 | * @author Tagir Valeev
38 | */
39 | /* package */class StreamContext {
40 | static final StreamContext SEQUENTIAL = new StreamContext(false);
41 | static final StreamContext PARALLEL = new StreamContext(true);
42 |
43 | boolean parallel;
44 | ForkJoinPool fjp;
45 | Runnable closeHandler;
46 |
47 | private StreamContext(boolean parallel) {
48 | this.parallel = parallel;
49 | }
50 |
51 | T terminate(Supplier terminalOperation) {
52 | return fjp.submit(terminalOperation::get).join();
53 | }
54 |
55 | T terminate(U value, Function terminalOperation) {
56 | return fjp.submit(() -> terminalOperation.apply(value)).join();
57 | }
58 |
59 | StreamContext parallel() {
60 | if (this == SEQUENTIAL)
61 | return PARALLEL;
62 | this.parallel = true;
63 | this.fjp = null;
64 | return this;
65 | }
66 |
67 | StreamContext sequential() {
68 | if (this == PARALLEL)
69 | return SEQUENTIAL;
70 | this.parallel = false;
71 | this.fjp = null;
72 | return this;
73 | }
74 |
75 | StreamContext parallel(ForkJoinPool fjp) {
76 | StreamContext context = detach();
77 | context.parallel = true;
78 | context.fjp = fjp;
79 | return context;
80 | }
81 |
82 | StreamContext detach() {
83 | if (this == PARALLEL || this == SEQUENTIAL)
84 | return new StreamContext(parallel);
85 | return this;
86 | }
87 |
88 | StreamContext onClose(Runnable r) {
89 | StreamContext context = detach();
90 | context.closeHandler = compose(context.closeHandler, r);
91 | return context;
92 | }
93 |
94 | void close() {
95 | if (closeHandler != null) {
96 | Runnable r = closeHandler;
97 | closeHandler = null;
98 | r.run();
99 | }
100 | }
101 |
102 | static Runnable compose(Runnable r1, Runnable r2) {
103 | if (r1 == null)
104 | return r2;
105 | return () -> {
106 | try {
107 | r1.run();
108 | } catch (Throwable t1) {
109 | try {
110 | r2.run();
111 | } catch (Throwable t2) {
112 | t1.addSuppressed(t2);
113 | }
114 | throw t1;
115 | }
116 | r2.run();
117 | };
118 | }
119 |
120 | StreamContext combine(BaseStream, ?> other) {
121 | if (other == null)
122 | return this;
123 | StreamContext otherStrategy = of(other);
124 | StreamContext result = this;
125 | if (other.isParallel() && !parallel)
126 | result = parallel();
127 | if (otherStrategy.closeHandler != null)
128 | result = result.onClose(otherStrategy.closeHandler);
129 | return result;
130 | }
131 |
132 | static StreamContext of(BaseStream, ?> stream) {
133 | if (stream instanceof BaseStreamEx)
134 | return ((BaseStreamEx, ?, ?, ?>) stream).context;
135 | return new StreamContext(stream.isParallel()).onClose(stream::close);
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/main/java/one/util/streamex/TailConcatSpliterator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import one.util.streamex.Internals.TailSpliterator;
19 |
20 | import java.util.Spliterator;
21 | import java.util.function.Consumer;
22 |
23 | /**
24 | * @author Tagir Valeev
25 | *
26 | * @param type of the elements
27 | */
28 | /* package */class TailConcatSpliterator implements TailSpliterator {
29 | private Spliterator left, right;
30 | private int characteristics;
31 | private long size;
32 |
33 | @SuppressWarnings("unchecked")
34 | public TailConcatSpliterator(Spliterator extends T> left, Spliterator extends T> right) {
35 | this.left = (Spliterator) left;
36 | this.right = (Spliterator) right;
37 | this.characteristics = left.characteristics() & right.characteristics() & (ORDERED | SIZED | SUBSIZED);
38 | this.size = left.estimateSize() + right.estimateSize();
39 | if (this.size < 0) {
40 | this.size = Long.MAX_VALUE;
41 | this.characteristics &= (~SIZED) & (~SUBSIZED);
42 | }
43 | }
44 |
45 | @Override
46 | public boolean tryAdvance(Consumer super T> action) {
47 | if (left != null) {
48 | if (left.tryAdvance(action)) {
49 | if (size > 0 && size != Long.MAX_VALUE)
50 | size--;
51 | return true;
52 | }
53 | left = null;
54 | }
55 | if (right != null)
56 | right = TailSpliterator.tryAdvanceWithTail(right, action);
57 | return right != null;
58 | }
59 |
60 | @Override
61 | public Spliterator tryAdvanceOrTail(Consumer super T> action) {
62 | if (left == null || !left.tryAdvance(action)) {
63 | Spliterator s = right;
64 | right = null;
65 | return s;
66 | }
67 | if (size > 0 && size != Long.MAX_VALUE)
68 | size--;
69 | return this;
70 | }
71 |
72 | @Override
73 | public void forEachRemaining(Consumer super T> action) {
74 | if (left != null)
75 | left.forEachRemaining(action);
76 | if (right != null)
77 | TailSpliterator.forEachWithTail(right, action);
78 | }
79 |
80 | @Override
81 | public Spliterator forEachOrTail(Consumer super T> action) {
82 | if (left != null)
83 | left.forEachRemaining(action);
84 | Spliterator s = right;
85 | right = null;
86 | return s;
87 | }
88 |
89 | @Override
90 | public Spliterator trySplit() {
91 | if (left == null)
92 | return right.trySplit();
93 | Spliterator s = left;
94 | left = null;
95 | return s;
96 | }
97 |
98 | @Override
99 | public long estimateSize() {
100 | if (left == null)
101 | return right == null ? 0 : right.estimateSize();
102 | return size;
103 | }
104 |
105 | @Override
106 | public int characteristics() {
107 | return characteristics;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/main/java/one/util/streamex/UnorderedCancellableSpliterator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import java.util.Spliterator;
19 | import java.util.concurrent.ConcurrentLinkedQueue;
20 | import java.util.concurrent.atomic.AtomicBoolean;
21 | import java.util.concurrent.atomic.AtomicInteger;
22 | import java.util.function.*;
23 |
24 | import static one.util.streamex.Internals.CancelException;
25 | import static one.util.streamex.Internals.CloneableSpliterator;
26 |
27 | /**
28 | * @author Tagir Valeev
29 | */
30 | /* package */class UnorderedCancellableSpliterator extends CloneableSpliterator> {
31 | private volatile Spliterator source;
32 | private final BiConsumer accumulator;
33 | private final Predicate cancelPredicate;
34 | private final Supplier supplier;
35 | private final ConcurrentLinkedQueue partialResults = new ConcurrentLinkedQueue<>();
36 | private final AtomicBoolean cancelled = new AtomicBoolean(false);
37 | private final AtomicInteger nPeers = new AtomicInteger(1);
38 | private final BinaryOperator combiner;
39 | private boolean flag;
40 |
41 | UnorderedCancellableSpliterator(Spliterator source, Supplier supplier, BiConsumer accumulator,
42 | BinaryOperator combiner, Predicate cancelPredicate) {
43 | this.source = source;
44 | this.supplier = supplier;
45 | this.accumulator = accumulator;
46 | this.combiner = combiner;
47 | this.cancelPredicate = cancelPredicate;
48 | }
49 |
50 | private boolean checkCancel(A acc) {
51 | if (cancelPredicate.test(acc)) {
52 | if (cancelled.compareAndSet(false, true)) {
53 | flag = true;
54 | return true;
55 | }
56 | }
57 | if (cancelled.get()) {
58 | flag = false;
59 | return true;
60 | }
61 | return false;
62 | }
63 |
64 | private boolean handleCancel(Consumer super A> action, A acc) {
65 | source = null;
66 | if (flag) {
67 | action.accept(acc);
68 | return true;
69 | }
70 | return false;
71 | }
72 |
73 | @Override
74 | public boolean tryAdvance(Consumer super A> action) {
75 | Spliterator source = this.source;
76 | if (source == null || cancelled.get()) {
77 | this.source = null;
78 | return false;
79 | }
80 | A acc = supplier.get();
81 | if (checkCancel(acc))
82 | return handleCancel(action, acc);
83 | try {
84 | source.forEachRemaining(t -> {
85 | accumulator.accept(acc, t);
86 | if (checkCancel(acc))
87 | throw new CancelException();
88 | });
89 | } catch (CancelException ex) {
90 | return handleCancel(action, acc);
91 | }
92 | A result = acc;
93 | while (true) {
94 | A acc2 = partialResults.poll();
95 | if (acc2 == null)
96 | break;
97 | result = combiner.apply(result, acc2);
98 | if (checkCancel(result))
99 | return handleCancel(action, result);
100 | }
101 | partialResults.offer(result);
102 | this.source = null;
103 | if (nPeers.decrementAndGet() == 0) {
104 | result = partialResults.poll();
105 | // non-cancelled finish
106 | while (true) {
107 | A acc2 = partialResults.poll();
108 | if (acc2 == null)
109 | break;
110 | result = combiner.apply(result, acc2);
111 | if (cancelPredicate.test(result))
112 | break;
113 | }
114 | this.source = null;
115 | action.accept(result);
116 | return true;
117 | }
118 | return false;
119 | }
120 |
121 | @Override
122 | public void forEachRemaining(Consumer super A> action) {
123 | tryAdvance(action);
124 | }
125 |
126 | @Override
127 | public Spliterator trySplit() {
128 | if (source == null || cancelled.get()) {
129 | source = null;
130 | return null;
131 | }
132 | Spliterator prefix = source.trySplit();
133 | if (prefix == null) {
134 | return null;
135 | }
136 | UnorderedCancellableSpliterator result = doClone();
137 | result.source = prefix;
138 | nPeers.incrementAndGet();
139 | return result;
140 | }
141 |
142 | @Override
143 | public long estimateSize() {
144 | return source == null ? 0 : source.estimateSize();
145 | }
146 |
147 | @Override
148 | public int characteristics() {
149 | return source == null ? SIZED : 0;
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/src/main/java/one/util/streamex/VerSpec.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package one.util.streamex;
18 |
19 | /**
20 | * @author Tagir Valeev
21 | */
22 | /* package */ interface VerSpec {
23 | VersionSpecific VER_SPEC = new VersionSpecific();
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/one/util/streamex/VersionSpecific.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import java.nio.CharBuffer;
19 | import java.util.ArrayList;
20 | import java.util.List;
21 | import java.util.Spliterator;
22 | import java.util.function.*;
23 | import java.util.stream.IntStream;
24 |
25 | /**
26 | * @author Tagir Valeev
27 | */
28 | /* package */ class VersionSpecific {
29 |
30 | > S callWhile(AbstractStreamEx stream, Predicate super T> predicate, boolean drop) {
31 | Spliterator spltr = stream.spliterator();
32 | return stream.supply(
33 | spltr.hasCharacteristics(Spliterator.ORDERED) ? new TakeDrop.TDOfRef<>(spltr, drop, false, predicate)
34 | : new TakeDrop.UnorderedTDOfRef(spltr, drop, false, predicate));
35 | }
36 |
37 | IntStreamEx callWhile(IntStreamEx stream, IntPredicate predicate, boolean drop) {
38 | return stream.delegate(new TakeDrop.TDOfInt(stream.spliterator(), drop, false, predicate));
39 | }
40 |
41 | LongStreamEx callWhile(LongStreamEx stream, LongPredicate predicate, boolean drop) {
42 | return stream.delegate(new TakeDrop.TDOfLong(stream.spliterator(), drop, false, predicate));
43 | }
44 |
45 | DoubleStreamEx callWhile(DoubleStreamEx stream, DoublePredicate predicate, boolean drop) {
46 | return stream.delegate(new TakeDrop.TDOfDouble(stream.spliterator(), drop, false, predicate));
47 | }
48 |
49 | StreamEx callMapMulti(AbstractStreamEx s, BiConsumer super T, ? super Consumer> mapper) {
50 | return s.flatCollection(e -> {
51 | List result = new ArrayList<>();
52 | mapper.accept(e, (Consumer) result::add);
53 | return result;
54 | });
55 | }
56 |
57 | IntStreamEx callMapMultiToInt(AbstractStreamEx s, BiConsumer super T, ? super IntConsumer> mapper) {
58 | return s.flatMapToInt(e -> {
59 | Internals.IntBuffer result = new Internals.IntBuffer();
60 | mapper.accept(e, (IntConsumer) result::add);
61 | return result.stream();
62 | });
63 | }
64 |
65 | LongStreamEx callMapMultiToLong(AbstractStreamEx s, BiConsumer super T, ? super LongConsumer> mapper) {
66 | return s.flatMapToLong(e -> {
67 | Internals.LongBuffer result = new Internals.LongBuffer();
68 | mapper.accept(e, (LongConsumer) result::add);
69 | return result.stream();
70 | });
71 | }
72 |
73 | DoubleStreamEx callMapMultiToDouble(AbstractStreamEx s, BiConsumer super T, ? super DoubleConsumer> mapper) {
74 | return s.flatMapToDouble(e -> {
75 | Internals.DoubleBuffer result = new Internals.DoubleBuffer();
76 | mapper.accept(e, (DoubleConsumer) result::add);
77 | return result.stream();
78 | });
79 | }
80 |
81 | IntStream ofChars(CharSequence seq) {
82 | // In JDK 8 there's only default chars() method which uses
83 | // IteratorSpliterator
84 | // In JDK 9 chars() method for most of implementations is much better
85 | return CharBuffer.wrap(seq).chars();
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/main/java/one/util/streamex/WithFirstSpliterator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import one.util.streamex.Internals.CloneableSpliterator;
19 |
20 | import java.util.Spliterator;
21 | import java.util.concurrent.locks.ReentrantLock;
22 | import java.util.function.BiFunction;
23 | import java.util.function.Consumer;
24 |
25 | /**
26 | * @author Tagir Valeev
27 | */
28 | /* package */final class WithFirstSpliterator extends CloneableSpliterator> implements Consumer {
29 | private static final int STATE_NONE = 0;
30 | private static final int STATE_FIRST_READ = 1;
31 | private static final int STATE_INIT = 2;
32 | private static final int STATE_EMPTY = 3;
33 |
34 | private ReentrantLock lock;
35 | private Spliterator source;
36 | private WithFirstSpliterator prefix;
37 | private volatile T first;
38 | private volatile int state = STATE_NONE;
39 | private final BiFunction super T, ? super T, ? extends R> mapper;
40 | private Consumer super R> action;
41 |
42 | WithFirstSpliterator(Spliterator source, BiFunction super T, ? super T, ? extends R> mapper) {
43 | this.source = source;
44 | this.mapper = mapper;
45 | }
46 |
47 | private void acquire() {
48 | if (lock != null && state == STATE_NONE) {
49 | lock.lock();
50 | }
51 | }
52 |
53 | private void release() {
54 | if (lock != null && lock.isHeldByCurrentThread()) {
55 | lock.unlock();
56 | }
57 | }
58 |
59 | @Override
60 | public boolean tryAdvance(Consumer super R> action) {
61 | if (state == STATE_NONE) {
62 | acquire();
63 | try {
64 | doInit();
65 | } finally {
66 | release();
67 | }
68 | }
69 | if (state == STATE_FIRST_READ) {
70 | state = STATE_INIT;
71 | action.accept(mapper.apply(first, first));
72 | return true;
73 | }
74 | if (state != STATE_INIT)
75 | return false;
76 | this.action = action;
77 | boolean hasNext = source.tryAdvance(this);
78 | this.action = null;
79 | return hasNext;
80 | }
81 |
82 | private void doInit() {
83 | int prefixState = state;
84 | if (prefixState != STATE_NONE)
85 | return;
86 | if (prefix != null) {
87 | prefix.doInit();
88 | prefixState = prefix.state;
89 | }
90 | if (prefixState == STATE_FIRST_READ || prefixState == STATE_INIT) {
91 | first = prefix.first;
92 | state = STATE_INIT;
93 | return;
94 | }
95 | state = source.tryAdvance(x -> first = x) ? STATE_FIRST_READ : STATE_EMPTY;
96 | }
97 |
98 | @Override
99 | public void forEachRemaining(Consumer super R> action) {
100 | acquire();
101 | int myState = state;
102 | this.action = action;
103 | if (myState == STATE_FIRST_READ || myState == STATE_INIT) {
104 | release();
105 | if (myState == STATE_FIRST_READ) {
106 | state = STATE_INIT;
107 | accept(first);
108 | }
109 | source.forEachRemaining(this);
110 | this.action = null;
111 | return;
112 | }
113 | try {
114 | Consumer init = x -> {
115 | if (state == STATE_NONE) {
116 | if (prefix != null) {
117 | prefix.doInit();
118 | }
119 | this.first = (prefix == null || prefix.state == STATE_EMPTY) ? x : prefix.first;
120 | state = STATE_INIT;
121 | }
122 | release();
123 | };
124 | source.forEachRemaining(init.andThen(this));
125 | this.action = null;
126 | } finally {
127 | release();
128 | }
129 | }
130 |
131 | @Override
132 | public Spliterator trySplit() {
133 | if (state != STATE_NONE)
134 | return null;
135 | Spliterator prefix;
136 | if (lock == null)
137 | lock = new ReentrantLock();
138 | acquire();
139 | try {
140 | if (state != STATE_NONE)
141 | return null;
142 | prefix = source.trySplit();
143 | if (prefix == null)
144 | return null;
145 | WithFirstSpliterator result = doClone();
146 | result.source = prefix;
147 | return this.prefix = result;
148 | } finally {
149 | release();
150 | }
151 | }
152 |
153 | @Override
154 | public long estimateSize() {
155 | return source.estimateSize();
156 | }
157 |
158 | @Override
159 | public int characteristics() {
160 | return NONNULL
161 | | (source.characteristics() & (DISTINCT | IMMUTABLE | CONCURRENT | ORDERED | (lock == null ? SIZED : 0)));
162 | }
163 |
164 | @Override
165 | public void accept(T x) {
166 | action.accept(mapper.apply(first, x));
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/src/test/java/one/util/streamex/AverageLongTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import org.junit.Test;
19 |
20 | import java.math.BigDecimal;
21 | import java.math.BigInteger;
22 | import java.math.MathContext;
23 | import java.util.Arrays;
24 | import java.util.OptionalDouble;
25 | import java.util.function.BiFunction;
26 | import java.util.function.Supplier;
27 | import java.util.stream.Collector;
28 | import java.util.stream.Collectors;
29 | import java.util.stream.IntStream;
30 | import java.util.stream.LongStream;
31 |
32 | import static one.util.streamex.Internals.AverageLong;
33 | import static one.util.streamex.TestHelpers.repeat;
34 | import static one.util.streamex.TestHelpers.withRandom;
35 | import static org.junit.Assert.assertEquals;
36 | import static org.junit.Assert.assertFalse;
37 |
38 | /**
39 | * @author Tagir Valeev
40 | */
41 | public class AverageLongTest {
42 |
43 | @Test
44 | public void testAverageLongNoOverflow() {
45 | AverageLong avg = new AverageLong();
46 | assertFalse(avg.result().isPresent());
47 | avg.accept(1);
48 | avg.accept(2);
49 | avg.accept(3);
50 | assertEquals(2.0, avg.result().getAsDouble(), 0.0);
51 |
52 | avg.accept(2);
53 | avg.accept(-4);
54 | avg.accept(8);
55 | assertEquals(2.0, avg.result().getAsDouble(), 0.0);
56 |
57 | AverageLong avg1 = new AverageLong();
58 | avg1.accept(-2);
59 | AverageLong avg2 = new AverageLong();
60 | avg2.accept(-2);
61 | assertEquals(-2.0, avg1.combine(avg2).result().getAsDouble(), 0.0);
62 |
63 | withRandom(r -> {
64 | int[] input = r.ints(1000).toArray();
65 | OptionalDouble expected = IntStream.of(input).average();
66 | assertEquals(expected, Arrays.stream(input)
67 | .collect(AverageLong::new, AverageLong::accept, AverageLong::combine).result());
68 |
69 | assertEquals(expected, Arrays.stream(input).parallel().collect(AverageLong::new, AverageLong::accept,
70 | AverageLong::combine).result());
71 | });
72 | }
73 |
74 | @Test
75 | public void testCombine() {
76 | withRandom(r -> repeat(100, i -> {
77 | AverageLong avg1 = new AverageLong();
78 | AverageLong avg2 = new AverageLong();
79 | long[] set1 = r.longs(100).toArray();
80 | long[] set2 = r.longs(100).toArray();
81 | double expected = LongStreamEx.of(set1).append(set2).boxed().collect(getBigIntegerAverager()).getAsDouble();
82 | LongStream.of(set1).forEach(avg1::accept);
83 | LongStream.of(set2).forEach(avg2::accept);
84 | assertEquals(expected, avg1.combine(avg2).result().getAsDouble(), Math.abs(expected / 1e14));
85 | }));
86 | }
87 |
88 | @Test
89 | public void testCompareToBigInteger() {
90 | withRandom(r -> {
91 | long[] input = LongStreamEx.of(r, 1000).toArray();
92 | Supplier supplier = () -> Arrays.stream(input);
93 | double expected = supplier.get().boxed().collect(getBigIntegerAverager()).getAsDouble();
94 | assertEquals(expected, supplier.get().collect(AverageLong::new, AverageLong::accept, AverageLong::combine)
95 | .result().getAsDouble(), Math.abs(expected) / 1e14);
96 | assertEquals(expected, supplier.get().parallel().collect(AverageLong::new, AverageLong::accept,
97 | AverageLong::combine).result().getAsDouble(), Math.abs(expected) / 1e14);
98 | });
99 | }
100 |
101 | private static Collector getBigIntegerAverager() {
102 | BiFunction finisher = (BigInteger sum, Long cnt) -> cnt == 0L ? OptionalDouble
103 | .empty()
104 | : OptionalDouble.of(new BigDecimal(sum).divide(BigDecimal.valueOf(cnt), MathContext.DECIMAL64)
105 | .doubleValue());
106 | return MoreCollectors.pairing(Collectors.reducing(BigInteger.ZERO,
107 | BigInteger::valueOf, BigInteger::add), Collectors.counting(), finisher);
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/test/java/one/util/streamex/CharSpliteratorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import org.junit.Test;
19 |
20 | import java.util.Arrays;
21 | import java.util.Spliterator;
22 |
23 | import static one.util.streamex.TestHelpers.*;
24 | import static org.junit.Assert.*;
25 |
26 | /**
27 | * @author Tagir Valeev
28 | */
29 | public class CharSpliteratorTest {
30 | @Test
31 | public void testBasics() {
32 | CharSpliterator spliterator = new CharSpliterator("abcd,efgh", ',', false);
33 | assertTrue(spliterator.hasCharacteristics(Spliterator.ORDERED));
34 | assertTrue(spliterator.hasCharacteristics(Spliterator.NONNULL));
35 | assertFalse(spliterator.hasCharacteristics(Spliterator.SORTED));
36 | assertFalse(spliterator.hasCharacteristics(Spliterator.SIZED));
37 | assertEquals(9, spliterator.estimateSize());
38 | assertTrue(spliterator.tryAdvance(a -> {
39 | }));
40 | assertEquals(4, spliterator.estimateSize());
41 | assertTrue(spliterator.tryAdvance(a -> {
42 | }));
43 | assertEquals(0, spliterator.estimateSize());
44 | }
45 |
46 | @Test
47 | public void testSpliterator() {
48 | // Empty string is processed differently by CharSpliterator, but this is
49 | // fixed in StreamEx.split
50 | checkSpliterator("split", Arrays.asList(), () -> new CharSpliterator("", ',', true));
51 | checkSpliterator("split", Arrays.asList(""), () -> new CharSpliterator("", ',', false));
52 | withRandom(r -> {
53 | String[] inputs = { ",", "abcd,e,f,gh,,,i,j,kl,,,,,,", ",", "abcdasdfgsdfgsdfgsdfgsdfgsdgdfsgs",
54 | "abcdasdfgsdfgsdfgsdfgsdfgsdgdfsgs,", "abcdasdfgs,dfgsdfgsdfgsdfgsdgdfsgs",
55 | "abcd,e,f,gh,,,i,j,kl,,,,,,x", "abcd,e,f,gh,,,i,j,kl,,,,,,x,",
56 | IntStreamEx.of(r, 0, 3).limit(r.nextInt(1000) + 1).elements(new int[] { ',', 'a', 'b' }).charsToString() };
57 | for (String input : inputs) {
58 | checkSpliterator(input, Arrays.asList(input.split(",")), () -> new CharSpliterator(input, ',', true));
59 | checkSpliterator(input, Arrays.asList(input.split(",", -1)), () -> new CharSpliterator(input, ',', false));
60 | }
61 | });
62 | }
63 |
64 | @Test
65 | public void testTrySplit() {
66 | String input = "a,b,c,d,e,f,g,h";
67 | CharSpliterator spliterator = new CharSpliterator(input, ',', false);
68 | assertEquals(-1, spliterator.getExactSizeIfKnown());
69 | assertEquals(15, spliterator.estimateSize());
70 | Spliterator prefix = spliterator.trySplit();
71 | assertEquals(7, prefix.estimateSize());
72 | assertEquals(7, spliterator.estimateSize());
73 | prefix = spliterator.trySplit();
74 | assertEquals(3, prefix.estimateSize());
75 | assertEquals(3, spliterator.estimateSize());
76 | consumeElement(spliterator, "g");
77 | consumeElement(spliterator, "h");
78 | consumeElement(prefix, "e");
79 | consumeElement(prefix, "f");
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/test/java/one/util/streamex/CollapseSpliteratorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import org.junit.Test;
19 |
20 | import java.util.*;
21 | import java.util.Map.Entry;
22 | import java.util.function.BiConsumer;
23 | import java.util.function.Function;
24 | import java.util.function.Supplier;
25 | import java.util.stream.Stream;
26 |
27 | import static one.util.streamex.TestHelpers.*;
28 | import static org.junit.Assert.assertEquals;
29 | import static org.junit.Assert.assertNotNull;
30 |
31 | /**
32 | * @author Tagir Valeev
33 | *
34 | */
35 | public class CollapseSpliteratorTest {
36 | private static void splitEquals(Spliterator source, BiConsumer, Spliterator> consumer) {
37 | Spliterator right = new CollapseSpliterator<>(Objects::equals, Function.identity(), Internals
38 | .selectFirst(), Internals.selectFirst(), source);
39 | Spliterator left = right.trySplit();
40 | assertNotNull(left);
41 | consumer.accept(left, right);
42 | }
43 |
44 | @Test
45 | public void testSimpleSplit() {
46 | List input = Arrays.asList(1, 1, 1, 2, 2, 2, 2, 2);
47 | splitEquals(input.spliterator(), (left, right) -> {
48 | List result = new ArrayList<>();
49 | left.forEachRemaining(result::add);
50 | right.forEachRemaining(result::add);
51 | assertEquals(Arrays.asList(1, 2), result);
52 | });
53 | splitEquals(input.spliterator(), (left, right) -> {
54 | List result = new ArrayList<>();
55 | List resultRight = new ArrayList<>();
56 | right.forEachRemaining(resultRight::add);
57 | left.forEachRemaining(result::add);
58 | result.addAll(resultRight);
59 | assertEquals(Arrays.asList(1, 2), result);
60 | });
61 | input = IntStreamEx.of(new Random(1), 100, 1, 10).sorted().boxed().toList();
62 | splitEquals(input.spliterator(), (left, right) -> {
63 | List result = new ArrayList<>();
64 | List resultRight = new ArrayList<>();
65 | for (int i = 0; i < 10; i++) {
66 | left.tryAdvance(result::add);
67 | right.tryAdvance(resultRight::add);
68 | }
69 | result.addAll(resultRight);
70 | assertEquals(IntStreamEx.range(1, 10).boxed().toList(), result);
71 | });
72 | input = IntStreamEx.constant(100, 100).append(2).prepend(1).boxed().toList();
73 | splitEquals(StreamEx.of(input).without(100).parallel().spliterator(), (left, right) -> {
74 | List result = new ArrayList<>();
75 | left.forEachRemaining(result::add);
76 | right.forEachRemaining(result::add);
77 | assertEquals(Arrays.asList(1, 2), result);
78 | });
79 | input = Arrays.asList(0, 0, 1, 1, 1, 1, 4, 6, 6, 3, 3, 10);
80 | splitEquals(Stream.concat(Stream.empty(), input.parallelStream()).spliterator(), (left, right) -> {
81 | List result = new ArrayList<>();
82 | left.forEachRemaining(result::add);
83 | right.forEachRemaining(result::add);
84 | assertEquals(Arrays.asList(0, 1, 4, 6, 3, 10), result);
85 | });
86 | }
87 |
88 | @Test
89 | public void testNonIdentity() {
90 | checkNonIdentity(Arrays.asList(1, 2, 5, 6, 7, 8, 10, 11, 15));
91 | checkNonIdentity(IntStreamEx.range(3, 100).prepend(1).boxed().toList());
92 | }
93 |
94 | private static void checkNonIdentity(List input) {
95 | checkSpliterator("collpase", () -> new CollapseSpliterator>(
96 | (a, b) -> (b - a == 1), a -> new AbstractMap.SimpleEntry<>(a, a),
97 | (acc, a) -> new AbstractMap.SimpleEntry<>(acc.getKey(), a), (a, b) -> new AbstractMap.SimpleEntry<>(a
98 | .getKey(), b.getValue()), input.spliterator()));
99 | }
100 |
101 | @Test
102 | public void testMultiSplit() {
103 | List input = Arrays.asList(0, 0, 1, 1, 1, 1, 4, 6, 6, 3, 3, 10);
104 | multiSplit(input::spliterator);
105 | multiSplit(() -> Stream.concat(Stream.empty(), input.parallelStream()).spliterator());
106 | }
107 |
108 | private static void multiSplit(Supplier> inputSpliterator) throws AssertionError {
109 | withRandom(r -> repeat(100, n -> {
110 | Spliterator spliterator = new CollapseSpliterator<>(Objects::equals, Function.identity(),
111 | Internals.selectFirst(), Internals.selectFirst(), inputSpliterator.get());
112 | List result = new ArrayList<>();
113 | List> spliterators = new ArrayList<>();
114 | spliterators.add(spliterator);
115 | for (int i = 0; i < 8; i++) {
116 | Spliterator split = spliterators.get(r.nextInt(spliterators.size())).trySplit();
117 | if (split != null)
118 | spliterators.add(split);
119 | }
120 | Collections.shuffle(spliterators, r);
121 | repeat(spliterators.size(), i -> spliterators.get(i - 1).forEachRemaining(result::add));
122 | assertEquals(6, result.size());
123 | }));
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/test/java/one/util/streamex/CombinationSpliteratorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import org.junit.Test;
19 |
20 | import java.util.Spliterator;
21 |
22 | import static java.util.Spliterator.*;
23 | import static org.junit.Assert.*;
24 |
25 | public class CombinationSpliteratorTest {
26 | @Test
27 | public void testStepJump() {
28 | int[][] nk = {
29 | {1, 1},
30 | {1, 10},
31 | {9, 10},
32 | {5, 10},
33 | {2, 5},
34 | {3, 5},
35 | {8, 16},
36 | {7, 20},
37 | {15, 20},
38 | {20, 20}
39 | };
40 | for (int[] ints : nk) {
41 | int k = ints[0];
42 | int n = ints[1];
43 | int[] values = IntStreamEx.range(k).toArray();
44 | long size = CombinationSpliterator.cnk(n, k);
45 | assertArrayEquals("n=" + n + ", k=" + k, values, CombinationSpliterator.jump(size - 1, k, n));
46 | for (long cur = 1; cur < size; cur++) {
47 | CombinationSpliterator.step(values, n);
48 | assertArrayEquals("n=" + n + ", k=" + k + ", cur = " + cur, values, CombinationSpliterator.jump(size - 1 - cur, k, n));
49 | }
50 | }
51 | }
52 |
53 | @Test
54 | public void testCharacteristics() {
55 | Spliterator spliterator = StreamEx.ofCombinations(10, 5).spliterator();
56 | assertEquals(DISTINCT | IMMUTABLE | NONNULL | ORDERED | SIZED | SUBSIZED, spliterator.characteristics());
57 | assertEquals(252, spliterator.estimateSize());
58 | }
59 |
60 | @Test
61 | public void testTrySplit() {
62 | Spliterator spliterator = StreamEx.ofCombinations(5, 5).spliterator();
63 | assertEquals(1, spliterator.estimateSize());
64 | assertNull(spliterator.trySplit());
65 |
66 | spliterator = StreamEx.ofCombinations(2, 1).spliterator();
67 | assertEquals(2, spliterator.estimateSize());
68 | assertNotNull(spliterator.trySplit());
69 |
70 | spliterator = StreamEx.ofCombinations(2, 1).spliterator();
71 | assertEquals(2, spliterator.estimateSize());
72 | boolean[] readZero = {false};
73 | assertTrue(spliterator.tryAdvance(x -> readZero[0] = x[0] == 0));
74 | assertTrue(readZero[0]);
75 | assertNull(spliterator.trySplit());
76 |
77 | spliterator = StreamEx.ofCombinations(4, 1).spliterator();
78 | assertEquals(4, spliterator.estimateSize());
79 | assertNotNull(spliterator.trySplit());
80 | assertEquals(2, spliterator.estimateSize());
81 | assertNotNull(spliterator.trySplit());
82 | assertEquals(1, spliterator.estimateSize());
83 | assertNull(spliterator.trySplit());
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/test/java/one/util/streamex/ConstSpliteratorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import one.util.streamex.ConstSpliterator.OfRef;
19 | import org.junit.Test;
20 |
21 | import java.util.Collections;
22 | import java.util.Spliterator;
23 |
24 | import static one.util.streamex.TestHelpers.checkSpliterator;
25 | import static one.util.streamex.TestHelpers.consumeElement;
26 | import static org.junit.Assert.*;
27 |
28 | /**
29 | * @author Tagir Valeev
30 | */
31 | public class ConstSpliteratorTest {
32 | @Test
33 | public void testConstant() {
34 | checkSpliterator("ref", Collections.nCopies(100, "val"), () -> new ConstSpliterator.OfRef<>("val", 100, false));
35 | checkSpliterator("ref", Collections.nCopies(100, Integer.MIN_VALUE), () -> new ConstSpliterator.OfInt(
36 | Integer.MIN_VALUE, 100, false));
37 | checkSpliterator("ref", Collections.nCopies(100, Long.MIN_VALUE), () -> new ConstSpliterator.OfLong(
38 | Long.MIN_VALUE, 100, false));
39 | checkSpliterator("ref", Collections.nCopies(100, Double.MIN_VALUE), () -> new ConstSpliterator.OfDouble(
40 | Double.MIN_VALUE, 100, false));
41 | }
42 |
43 | @Test
44 | public void testCharacteristics() {
45 | OfRef spltr = new ConstSpliterator.OfRef<>("val", 4, true);
46 | assertTrue(spltr.hasCharacteristics(Spliterator.ORDERED));
47 | assertTrue(spltr.hasCharacteristics(Spliterator.SIZED));
48 | assertTrue(spltr.hasCharacteristics(Spliterator.SUBSIZED));
49 | assertTrue(spltr.hasCharacteristics(Spliterator.IMMUTABLE));
50 | assertFalse(new ConstSpliterator.OfRef<>("val", 4, false).hasCharacteristics(Spliterator.ORDERED));
51 | }
52 |
53 | @Test
54 | public void testSplit() {
55 | OfRef spltr = new ConstSpliterator.OfRef<>("val", 4, true);
56 | assertEquals(4, spltr.getExactSizeIfKnown());
57 | spltr = spltr.trySplit();
58 | assertEquals(2, spltr.getExactSizeIfKnown());
59 | spltr = spltr.trySplit();
60 | assertEquals(1, spltr.getExactSizeIfKnown());
61 | assertNull(spltr.trySplit());
62 | consumeElement(spltr, "val");
63 | assertEquals(0, spltr.getExactSizeIfKnown());
64 | assertNull(spltr.trySplit());
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/test/java/one/util/streamex/CrossSpliteratorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import org.junit.Test;
19 |
20 | import java.util.*;
21 |
22 | import static one.util.streamex.TestHelpers.checkSpliterator;
23 | import static org.junit.Assert.*;
24 |
25 | /**
26 | * @author Tagir Valeev
27 | */
28 | public class CrossSpliteratorTest {
29 | @Test
30 | public void testCrossToList() {
31 | for (int limit : new int[] { 1, 2, 4, 9 }) {
32 | List> input = Collections.nCopies(3, IntStreamEx.range(limit).boxed().toList());
33 | List> expected = IntStreamEx.range(limit * limit * limit).mapToObj(
34 | i -> Arrays.asList(i / limit / limit, i / limit % limit, i % limit)).toList();
35 | checkSpliterator("cross", expected, () -> new CrossSpliterator.ToList<>(input));
36 | }
37 | }
38 |
39 | @Test
40 | public void testCrossReduce() {
41 | for (int limit : new int[] { 1, 2, 4, 9 }) {
42 | List> input = Collections.nCopies(3, IntStreamEx.range(limit).boxed().toList());
43 | List expected = IntStreamEx.range(limit * limit * limit).mapToObj(
44 | i -> "" + (i / limit / limit) + (i / limit % limit) + (i % limit)).toList();
45 | checkSpliterator("cross", expected, () -> new CrossSpliterator.Reducing<>(input, "", (s, b) -> s + b));
46 | }
47 | }
48 |
49 | @Test
50 | public void testBigSize() {
51 | List> input = new ArrayList<>();
52 | input.add(IntStreamEx.rangeClosed(1, 20).boxed().toList());
53 | input.addAll(Collections.nCopies(18, IntStreamEx.rangeClosed(1, 10).boxed().toList()));
54 | Spliterator> spltr = new CrossSpliterator.ToList<>(input);
55 | assertFalse(spltr.hasCharacteristics(Spliterator.SIZED));
56 | assertEquals(Long.MAX_VALUE, spltr.estimateSize());
57 | spltr.trySplit();
58 | assertFalse(spltr.hasCharacteristics(Spliterator.SIZED));
59 | assertEquals(Long.MAX_VALUE, spltr.estimateSize());
60 | spltr.trySplit();
61 | assertTrue(spltr.hasCharacteristics(Spliterator.SIZED));
62 | assertEquals(5_000_000_000_000_000_000L, spltr.estimateSize());
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/test/java/one/util/streamex/DistinctSpliteratorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import org.junit.Test;
19 |
20 | import java.util.Arrays;
21 | import java.util.HashSet;
22 | import java.util.Set;
23 | import java.util.Spliterator;
24 | import java.util.stream.IntStream;
25 |
26 | import static one.util.streamex.TestHelpers.checkSpliterator;
27 | import static org.junit.Assert.assertEquals;
28 | import static org.junit.Assert.assertTrue;
29 |
30 | /**
31 | * @author Tagir Valeev
32 | */
33 | public class DistinctSpliteratorTest {
34 |
35 | @Test
36 | public void testSpliterator() {
37 | checkSpliterator("Distinct2", Arrays.asList("b"), () -> new DistinctSpliterator<>(Arrays.asList("a", null, "b",
38 | "c", "b", null, "c", "b").spliterator(), 3));
39 | checkSpliterator("Distinct34", Arrays.asList(0), () -> new DistinctSpliterator<>(IntStream.range(0, 100).map(
40 | x -> x % 3).boxed().spliterator(), 34));
41 |
42 | assertEquals(Spliterator.DISTINCT | Spliterator.ORDERED, new DistinctSpliterator<>(Arrays.asList("a", null,
43 | "b", "c", "b", null, "c", "b").spliterator(), 3).characteristics());
44 | assertEquals(Spliterator.DISTINCT | Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.SORTED
45 | | Spliterator.NONNULL, new DistinctSpliterator<>(IntStream.range(0, 100).spliterator(), 3)
46 | .characteristics());
47 | assertEquals(100, new DistinctSpliterator<>(IntStream.range(0, 100).spliterator(), 3).estimateSize());
48 | }
49 |
50 | @Test
51 | public void testAdvanceSplit() {
52 | DistinctSpliterator ds = new DistinctSpliterator<>(Arrays.asList("a", null, "b", "c", "b", null, "c",
53 | "b").spliterator(), 2);
54 | Set result = new HashSet<>();
55 | assertTrue(ds.tryAdvance(result::add));
56 | assertTrue(ds.tryAdvance(result::add));
57 | Spliterator prefix = ds.trySplit();
58 | prefix.forEachRemaining(result::add);
59 | ds.forEachRemaining(result::add);
60 | assertEquals(StreamEx.of(null, "b", "c").toSet(), result);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/test/java/one/util/streamex/EntryStreamInternalTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import org.junit.FixMethodOrder;
19 | import org.junit.Test;
20 | import org.junit.runners.MethodSorters;
21 |
22 | import java.util.LinkedHashMap;
23 | import java.util.Map;
24 |
25 | import static org.junit.Assert.assertSame;
26 |
27 | /**
28 | * @author Tagir Valeev
29 | */
30 | @FixMethodOrder(MethodSorters.NAME_ASCENDING)
31 | public class EntryStreamInternalTest {
32 |
33 | @Test
34 | public void testCreate() {
35 | EntryStream stream = EntryStream.of(createMap());
36 | assertSame(stream.stream(), EntryStream.of(stream).stream());
37 | assertSame(stream.stream(), EntryStream.of(StreamEx.of(EntryStream.of(stream))).stream());
38 | }
39 |
40 | private static Map createMap() {
41 | Map data = new LinkedHashMap<>();
42 | data.put("a", 1);
43 | data.put("bb", 22);
44 | data.put("ccc", 33);
45 | return data;
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/test/java/one/util/streamex/IfEmptySpliteratorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package one.util.streamex;
18 |
19 | import org.junit.Test;
20 |
21 | import java.util.*;
22 | import java.util.function.Supplier;
23 |
24 | import static one.util.streamex.TestHelpers.checkSpliterator;
25 | import static one.util.streamex.TestHelpers.consumeElement;
26 | import static org.junit.Assert.*;
27 |
28 | public class IfEmptySpliteratorTest {
29 | @Test
30 | public void testSpliterator() {
31 | List data = IntStreamEx.range(1000).boxed().toList();
32 | checkSpliterator("++", data, () -> new IfEmptySpliterator<>(data.spliterator(), data.spliterator()));
33 | checkSpliterator("-+", data, () -> new IfEmptySpliterator<>(Spliterators.emptySpliterator(), data.spliterator()));
34 | checkSpliterator("+-", data, () -> new IfEmptySpliterator<>(data.spliterator(), Spliterators.emptySpliterator()));
35 | checkSpliterator("--", Collections.emptyList(), () -> new IfEmptySpliterator<>(Spliterators.emptySpliterator(), Spliterators.emptySpliterator()));
36 | }
37 |
38 | @Test
39 | public void testCharacteristics() {
40 | Spliterator sortedSpltr = StreamEx.of("foo", "bar", "baz").sorted().ifEmpty(
41 | StreamEx.of("foo", "bar", "baz").sorted()).spliterator();
42 | assertFalse(sortedSpltr.hasCharacteristics(Spliterator.SORTED));
43 | consumeElement(sortedSpltr, "bar");
44 | assertFalse(sortedSpltr.hasCharacteristics(Spliterator.SORTED));
45 | assertTrue(StreamEx.of("foo", "bar", "baz").ifEmpty(StreamEx.of(new HashSet<>())).spliterator()
46 | .hasCharacteristics(Spliterator.ORDERED));
47 | List list = Collections.singletonList("foo");
48 | Spliterator spliterator = StreamEx.empty().ifEmpty(list.stream()).spliterator();
49 | consumeElement(spliterator, "foo");
50 | assertEquals(list.spliterator().characteristics(), spliterator.characteristics());
51 | }
52 |
53 | @Test
54 | public void testSize() {
55 | Spliterator spliterator = StreamEx.of("foo", "bar", "baz").ifEmpty("qux").spliterator();
56 | assertEquals(3, spliterator.getExactSizeIfKnown());
57 | consumeElement(spliterator, "foo");
58 | assertEquals(2, spliterator.getExactSizeIfKnown());
59 | assertEquals(1, StreamEx.empty().ifEmpty("qux").spliterator().getExactSizeIfKnown());
60 | }
61 |
62 | @Test
63 | public void testFiltered() {
64 | List data = IntStreamEx.range(1000).boxed().toList();
65 | Supplier> allMatch = () -> data.parallelStream().filter(x -> x >= 0).spliterator();
66 | Supplier> noneMatch = () -> data.parallelStream().filter(x -> x < 0).spliterator();
67 | Supplier> lastMatch = () -> data.parallelStream().filter(x -> x == 999).spliterator();
68 | checkSpliterator("++", data, () -> new IfEmptySpliterator<>(allMatch.get(), allMatch.get()));
69 | checkSpliterator("l+", Collections.singletonList(999), () -> new IfEmptySpliterator<>(lastMatch.get(), allMatch.get()));
70 | checkSpliterator("-+", data, () -> new IfEmptySpliterator<>(noneMatch.get(), allMatch.get()));
71 | checkSpliterator("+-", data, () -> new IfEmptySpliterator<>(allMatch.get(), noneMatch.get()));
72 | checkSpliterator("--", Collections.emptyList(), () -> new IfEmptySpliterator<>(noneMatch.get(), noneMatch.get()));
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/test/java/one/util/streamex/InternalsTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, 2024 StreamEx contributors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package one.util.streamex;
17 |
18 | import one.util.streamex.Internals.PairBox;
19 | import org.junit.Test;
20 |
21 | import java.util.*;
22 |
23 | import static one.util.streamex.Internals.ArrayCollection;
24 | import static one.util.streamex.Internals.PartialCollector;
25 | import static org.junit.Assert.*;
26 |
27 | /**
28 | * Tests for non-public APIs in StreamExInternals
29 | *
30 | * @author Tagir Valeev
31 | */
32 | public class InternalsTest {
33 | @Test
34 | public void testArrayCollection() {
35 | Collection