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

amaembo / streamex / #677

02 Nov 2024 08:50AM UTC coverage: 99.673%. Remained the same
#677

push

amaembo
Optimize imports

5786 of 5805 relevant lines covered (99.67%)

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, 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.*;
19
import java.util.function.BiFunction;
20
import java.util.function.Consumer;
21
import java.util.stream.StreamSupport;
22

23
/**
24
 * @author Tagir Valeev
25
 */
26
/* package */abstract class CrossSpliterator<T, A> implements Spliterator<A> {
27
    long est;
28
    int splitPos;
29
    final Spliterator<T>[] spliterators;
30
    final Collection<T>[] collections;
31

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

49
    abstract Spliterator<A> doSplit(long prefixEst, Spliterator<T>[] prefixSpliterators,
50
            Collection<T>[] prefixCollections);
51

52
    abstract void accumulate(int pos, T t);
53

54
    CrossSpliterator(long est, int splitPos, Spliterator<T>[] spliterators, Collection<T>[] collections) {
1✔
55
        this.est = est;
1✔
56
        this.splitPos = splitPos;
1✔
57
        this.spliterators = spliterators;
1✔
58
        this.collections = collections;
1✔
59
    }
1✔
60

61
    static final class Reducing<T, A> extends CrossSpliterator<T, A> {
62
        private A[] elements;
63
        private final BiFunction<A, ? super T, A> accumulator;
64

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

73
        private Reducing(long est, int splitPos, BiFunction<A, ? super T, A> accumulator,
74
                Spliterator<T>[] spliterators, Collection<T>[] collections, A[] elements) {
75
            super(est, splitPos, spliterators, collections);
1✔
76
            this.accumulator = accumulator;
1✔
77
            this.elements = elements;
1✔
78
        }
1✔
79

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

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

109
        @Override
110
        Spliterator<A> doSplit(long prefixEst, Spliterator<T>[] prefixSpliterators, Collection<T>[] prefixCollections) {
111
            return new Reducing<>(prefixEst, splitPos, accumulator, prefixSpliterators, prefixCollections, elements
1✔
112
                    .clone());
1✔
113
        }
114

115
        @Override
116
        void accumulate(int pos, T t) {
117
            elements[pos + 1] = accumulator.apply(elements[pos], t);
1✔
118
        }
1✔
119
    }
120

121
    static final class ToList<T> extends CrossSpliterator<T, List<T>> {
122
        private List<T> elements;
123

124
        @SuppressWarnings("unchecked")
125
        ToList(Collection<? extends Collection<T>> source) {
126
            super(source);
1✔
127
            this.elements = (List<T>) Arrays.asList(new Object[collections.length]);
1✔
128
        }
1✔
129

130
        private ToList(long est, int splitPos, Spliterator<T>[] spliterators, Collection<T>[] collections,
131
                List<T> elements) {
132
            super(est, splitPos, spliterators, collections);
1✔
133
            this.elements = elements;
1✔
134
        }
1✔
135

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

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

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

172
        @Override
173
        void accumulate(int pos, T t) {
174
            elements.set(pos, t);
1✔
175
        }
1✔
176
    }
177

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

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

238
    @Override
239
    public long estimateSize() {
240
        return est;
1✔
241
    }
242

243
    @Override
244
    public int characteristics() {
245
        int sized = est < Long.MAX_VALUE ? SIZED : 0;
1✔
246
        return ORDERED | sized;
1✔
247
    }
248
}
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