• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

amaembo / streamex / #673

29 Nov 2023 08:51AM UTC coverage: 99.69%. Remained the same
#673

push

web-flow
Merge pull request #274 from Kivanval/fix/desc

Correcting a comment in StreamEx.java

5787 of 5805 relevant lines covered (99.69%)

1.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.22
/src/main/java/one/util/streamex/CrossSpliterator.java
1
/*
2
 * Copyright 2015, 2023 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.ArrayList;
19
import java.util.Arrays;
20
import java.util.Collection;
21
import java.util.List;
22
import java.util.Spliterator;
23
import java.util.Spliterators;
24
import java.util.function.BiFunction;
25
import java.util.function.Consumer;
26
import java.util.stream.StreamSupport;
27

28
/**
29
 * @author Tagir Valeev
30
 */
31
/* package */abstract class CrossSpliterator<T, A> implements Spliterator<A> {
32
    long est;
33
    int splitPos;
34
    final Spliterator<T>[] spliterators;
35
    final Collection<T>[] collections;
36

37
    @SuppressWarnings("unchecked")
38
    CrossSpliterator(Collection<? extends Collection<T>> source) {
1✔
39
        this.splitPos = 0;
1✔
40
        long est = 1;
1✔
41
        try {
42
            for (Collection<T> c : source) {
1✔
43
                long size = c.size();
1✔
44
                est = StrictMath.multiplyExact(est, size);
1✔
45
            }
1✔
46
        } catch (ArithmeticException e) {
1✔
47
            est = Long.MAX_VALUE;
1✔
48
        }
1✔
49
        this.est = est;
1✔
50
        this.collections = source.toArray(new Collection[0]);
1✔
51
        this.spliterators = new Spliterator[collections.length];
1✔
52
    }
1✔
53

54
    abstract Spliterator<A> doSplit(long prefixEst, Spliterator<T>[] prefixSpliterators,
55
            Collection<T>[] prefixCollections);
56

57
    abstract void accumulate(int pos, T t);
58

59
    CrossSpliterator(long est, int splitPos, Spliterator<T>[] spliterators, Collection<T>[] collections) {
1✔
60
        this.est = est;
1✔
61
        this.splitPos = splitPos;
1✔
62
        this.spliterators = spliterators;
1✔
63
        this.collections = collections;
1✔
64
    }
1✔
65

66
    static final class Reducing<T, A> extends CrossSpliterator<T, A> {
67
        private A[] elements;
68
        private final BiFunction<A, ? super T, A> accumulator;
69

70
        @SuppressWarnings("unchecked")
71
        Reducing(Collection<? extends Collection<T>> source, A identity, BiFunction<A, ? super T, A> accumulator) {
72
            super(source);
1✔
73
            this.accumulator = accumulator;
1✔
74
            this.elements = (A[]) new Object[collections.length + 1];
1✔
75
            this.elements[0] = identity;
1✔
76
        }
1✔
77

78
        private Reducing(long est, int splitPos, BiFunction<A, ? super T, A> accumulator,
79
                Spliterator<T>[] spliterators, Collection<T>[] collections, A[] elements) {
80
            super(est, splitPos, spliterators, collections);
1✔
81
            this.accumulator = accumulator;
1✔
82
            this.elements = elements;
1✔
83
        }
1✔
84

85
        @Override
86
        public boolean tryAdvance(Consumer<? super A> action) {
87
            if (elements == null)
1✔
88
                return false;
1✔
89
            if (est < Long.MAX_VALUE && est > 0)
1✔
90
                est--;
1✔
91
            int l = collections.length;
1✔
92
            if (advance(l - 1)) {
1✔
93
                action.accept(elements[l]);
1✔
94
                return true;
1✔
95
            }
96
            elements = null;
1✔
97
            est = 0;
1✔
98
            return false;
1✔
99
        }
100

101
        @Override
102
        public void forEachRemaining(Consumer<? super A> action) {
103
            if (elements == null)
1✔
104
                return;
1✔
105
            int l = collections.length;
1✔
106
            A[] e = elements;
1✔
107
            while (advance(l - 1)) {
1✔
108
                action.accept(e[l]);
1✔
109
            }
110
            elements = null;
1✔
111
            est = 0;
1✔
112
        }
1✔
113

114
        @Override
115
        Spliterator<A> doSplit(long prefixEst, Spliterator<T>[] prefixSpliterators, Collection<T>[] prefixCollections) {
116
            return new Reducing<>(prefixEst, splitPos, accumulator, prefixSpliterators, prefixCollections, elements
1✔
117
                    .clone());
1✔
118
        }
119

120
        @Override
121
        void accumulate(int pos, T t) {
122
            elements[pos + 1] = accumulator.apply(elements[pos], t);
1✔
123
        }
1✔
124
    }
125

126
    static final class ToList<T> extends CrossSpliterator<T, List<T>> {
127
        private List<T> elements;
128

129
        @SuppressWarnings("unchecked")
130
        ToList(Collection<? extends Collection<T>> source) {
131
            super(source);
1✔
132
            this.elements = (List<T>) Arrays.asList(new Object[collections.length]);
1✔
133
        }
1✔
134

135
        private ToList(long est, int splitPos, Spliterator<T>[] spliterators, Collection<T>[] collections,
136
                List<T> elements) {
137
            super(est, splitPos, spliterators, collections);
1✔
138
            this.elements = elements;
1✔
139
        }
1✔
140

141
        @Override
142
        public boolean tryAdvance(Consumer<? super List<T>> action) {
143
            if (elements == null)
1✔
144
                return false;
1✔
145
            if (est < Long.MAX_VALUE && est > 0)
1✔
146
                est--;
1✔
147
            if (advance(collections.length - 1)) {
1✔
148
                action.accept(new ArrayList<>(elements));
1✔
149
                return true;
1✔
150
            }
151
            elements = null;
1✔
152
            est = 0;
1✔
153
            return false;
1✔
154
        }
155

156
        @Override
157
        public void forEachRemaining(Consumer<? super List<T>> action) {
158
            if (elements == null)
1✔
159
                return;
1✔
160
            List<T> e = elements;
1✔
161
            int l = collections.length - 1;
1✔
162
            while (advance(l)) {
1✔
163
                action.accept(new ArrayList<>(e));
1✔
164
            }
165
            elements = null;
1✔
166
            est = 0;
1✔
167
        }
1✔
168

169
        @Override
170
        Spliterator<List<T>> doSplit(long prefixEst, Spliterator<T>[] prefixSpliterators,
171
                Collection<T>[] prefixCollections) {
172
            @SuppressWarnings("unchecked")
173
            List<T> prefixElements = (List<T>) Arrays.asList(elements.toArray());
1✔
174
            return new ToList<>(prefixEst, splitPos, prefixSpliterators, prefixCollections, prefixElements);
1✔
175
        }
176

177
        @Override
178
        void accumulate(int pos, T t) {
179
            elements.set(pos, t);
1✔
180
        }
1✔
181
    }
182

183
    boolean advance(int i) {
184
        if (spliterators[i] == null) {
1✔
185
            if (i > 0 && collections[i - 1] != null && !advance(i - 1))
1✔
186
                return false;
1✔
187
            spliterators[i] = collections[i].spliterator();
1✔
188
        }
189
        Consumer<? super T> action = t -> accumulate(i, t);
1✔
190
        if (!spliterators[i].tryAdvance(action)) {
1✔
191
            if (i == 0 || collections[i - 1] == null || !advance(i - 1))
1✔
192
                return false;
1✔
193
            spliterators[i] = collections[i].spliterator();
1✔
194
            return spliterators[i].tryAdvance(action);
1✔
195
        }
196
        return true;
1✔
197
    }
198

199
    @Override
200
    public Spliterator<A> trySplit() {
201
        if (spliterators[splitPos] == null)
1✔
202
            spliterators[splitPos] = collections[splitPos].spliterator();
1✔
203
        Spliterator<T> res = spliterators[splitPos].trySplit();
1✔
204
        if (res == null) {
1✔
205
            if (splitPos == spliterators.length - 1)
1✔
206
                return null;
1✔
207
            @SuppressWarnings("unchecked")
208
            T[] arr = (T[]) StreamSupport.stream(spliterators[splitPos], false).toArray();
1✔
209
            if (arr.length == 0)
1✔
210
                return null;
×
211
            if (arr.length == 1) {
1✔
212
                accumulate(splitPos, arr[0]);
1✔
213
                splitPos++;
1✔
214
                return trySplit();
1✔
215
            }
216
            spliterators[splitPos] = Spliterators.spliterator(arr, Spliterator.ORDERED);
1✔
217
            return trySplit();
1✔
218
        }
219
        long prefixEst = Long.MAX_VALUE;
1✔
220
        long newEst = spliterators[splitPos].getExactSizeIfKnown();
1✔
221
        if (newEst == -1) {
1✔
222
            newEst = Long.MAX_VALUE;
1✔
223
        } else {
224
            try {
225
                for (int i = splitPos + 1; i < collections.length; i++) {
1✔
226
                    long size = collections[i].size();
1✔
227
                    newEst = StrictMath.multiplyExact(newEst, size);
1✔
228
                }
229
                if (est != Long.MAX_VALUE)
1✔
230
                    prefixEst = est - newEst;
1✔
231
            } catch (ArithmeticException e) {
1✔
232
                newEst = Long.MAX_VALUE;
1✔
233
            }
1✔
234
        }
235
        Spliterator<T>[] prefixSpliterators = spliterators.clone();
1✔
236
        Collection<T>[] prefixCollections = collections.clone();
1✔
237
        prefixSpliterators[splitPos] = res;
1✔
238
        this.est = newEst;
1✔
239
        Arrays.fill(spliterators, splitPos + 1, spliterators.length, null);
1✔
240
        return doSplit(prefixEst, prefixSpliterators, prefixCollections);
1✔
241
    }
242

243
    @Override
244
    public long estimateSize() {
245
        return est;
1✔
246
    }
247

248
    @Override
249
    public int characteristics() {
250
        int sized = est < Long.MAX_VALUE ? SIZED : 0;
1✔
251
        return ORDERED | sized;
1✔
252
    }
253
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc