17
17
*/
18
18
public final class Eithers {
19
19
20
- static final Set <Collector .Characteristics > CH_NOID = Set .of ();
20
+ private static final Set <Collector .Characteristics > CH_NOID = Set .of ();
21
21
22
- private Eithers () {
22
+ /**
23
+ * Returns a {@code Collector} that accumulates the input elements into
24
+ * a Right containing all values in the original order,
25
+ * but only if there are no Left instances in the stream.
26
+ * If the stream does contain a Left instance, it discards the Right instances and
27
+ * accumulates a Left instance, which contains the first LHS value in the stream,
28
+ * in encounter order.
29
+ *
30
+ * @param <L> the type of the LHS values in the stream
31
+ * @param <R> the type of the RHS values in the stream
32
+ * @return a {@code Collector} which collects all the input elements into
33
+ * a Right containing all RHS values in the stream, or,
34
+ * if an LHS value exists, a Left containing the first LHS value
35
+ */
36
+ public static <L , R >
37
+ Collector <Either <? extends L , ? extends R >, ?, Either <L , List <R >>>
38
+ firstFailure () {
39
+
40
+ BiConsumer <FirstFailureAcc <L , R >, Either <? extends L , ? extends R >> accumulator = (acc , either ) ->
41
+ either .ifLeftOrElse (acc ::addLeft , acc ::addRight );
42
+
43
+ BinaryOperator <FirstFailureAcc <L , R >> combiner = (acc , other ) ->
44
+ (FirstFailureAcc <L , R >) acc .combine (other );
45
+
46
+ return new CollectorImpl <>(FirstFailureAcc ::new , accumulator , combiner , FirstFailureAcc ::finish );
47
+ }
48
+
49
+ /**
50
+ * Returns a {@code Collector} that accumulates the input elements into
51
+ * a Right containing all values in the original order,
52
+ * but only if there are no Left instances in the stream.
53
+ * If the stream does contain a Left instance, it discards the Right instances and
54
+ * accumulates a Left containing only the LHS values,
55
+ * in encounter order.
56
+ *
57
+ * @param <L> the type of the LHS values in the stream
58
+ * @param <R> the type of the RHS values in the stream
59
+ * @return a {@code Collector} which collects all the input elements into
60
+ * a Right containing all RHS values in the stream,
61
+ * or, if an LHS value exists, a Left containing a nonempty list
62
+ * of all LHS values in the stream
63
+ */
64
+ public static <L , R >
65
+ Collector <Either <? extends L , ? extends R >, ?, Either <List <L >, List <R >>>
66
+ allFailures () {
67
+
68
+ BiConsumer <AllFailuresAcc <L , R >, Either <? extends L , ? extends R >> accumulator = (acc , either ) ->
69
+ either .ifLeftOrElse (acc ::addLeft , acc ::addRight );
70
+
71
+ BinaryOperator <AllFailuresAcc <L , R >> combiner = (acc , other ) ->
72
+ (AllFailuresAcc <L , R >) acc .combine (other );
73
+
74
+ return new CollectorImpl <>(AllFailuresAcc ::new , accumulator , combiner , AllFailuresAcc ::finish );
75
+ }
76
+
77
+ /**
78
+ * Returns a {@code Collector} that accumulates the input elements into
79
+ * a new {@code List}. There are no guarantees on the type, mutability,
80
+ * serializability, or thread-safety of the {@code List} returned.
81
+ * The final list is wrapped in an {@code Optional},
82
+ * which is empty if and only if the list is empty.
83
+ *
84
+ * @see #optionalList(List)
85
+ * @param <T> the type of the input elements
86
+ * @return a list of the RHS values in the stream,
87
+ * or, if an LHS value exists, a nonempty list of all LHS values
88
+ */
89
+ public static <T > Collector <T , ?, Optional <List <T >>> toOptionalList () {
90
+ return Collectors .collectingAndThen (
91
+ Collectors .toList (),
92
+ Eithers ::optionalList );
93
+ }
94
+
95
+ /**
96
+ * If the provided list is empty, returns an empty {@link Optional}.
97
+ * Otherwise, returns an {@code Optional} containing the nonempty
98
+ * input list.
99
+ *
100
+ * <p>Note: The resulting {@code Optional} might be used in a
101
+ * {@link Either#filter(Function) filter} or
102
+ * {@link Either#filterLeft(Function) filterLeft} operation.
103
+ *
104
+ * @see #toOptionalList()
105
+ * @param values a list of objects
106
+ * @param <T> the type of the members of {@code values}
107
+ * @return an {@code Optional} which is either empty, or
108
+ * contains a nonempty list
109
+ */
110
+ public static <T > Optional <List <T >> optionalList (List <? extends T > values ) {
111
+ if (values .isEmpty ()) {
112
+ return Optional .empty ();
113
+ }
114
+ @ SuppressWarnings ("unchecked" )
115
+ List <T > result = (List <T >) values ;
116
+ return Optional .of (result );
23
117
}
24
118
25
119
/**
@@ -28,7 +122,7 @@ private Eithers() {
28
122
* @param <T> the type of elements to be collected
29
123
* @param <R> the type of the result
30
124
*/
31
- private static class CollectorImpl <T , A , R > implements Collector <T , A , R > {
125
+ private static final class CollectorImpl <T , A , R > implements Collector <T , A , R > {
32
126
final Supplier <A > supplier ;
33
127
final BiConsumer <A , T > accumulator ;
34
128
final BinaryOperator <A > combiner ;
@@ -82,10 +176,12 @@ static abstract class Acc<L, C, R> {
82
176
abstract void combineLeft (C otherLeft );
83
177
84
178
// nullable
85
- abstract C left ();
179
+ abstract C leftColl ();
180
+
181
+ abstract void addLeft (L left );
86
182
87
183
final void addRight (R value ) {
88
- if (left () != null ) {
184
+ if (leftColl () != null ) {
89
185
return ;
90
186
}
91
187
if (right == null ) {
@@ -95,11 +191,11 @@ final void addRight(R value) {
95
191
}
96
192
97
193
final Acc <L , C , R > combine (Acc <L , C , R > other ) {
98
- if (left () != null ) {
99
- combineLeft (other .left ());
194
+ if (leftColl () != null ) {
195
+ combineLeft (other .leftColl ());
100
196
return this ;
101
197
}
102
- if (other .left () != null ) {
198
+ if (other .leftColl () != null ) {
103
199
return other ;
104
200
}
105
201
if (other .right == null ) {
@@ -114,33 +210,34 @@ final Acc<L, C, R> combine(Acc<L, C, R> other) {
114
210
}
115
211
116
212
final Either <C , List <R >> finish () {
117
- C left = left ();
213
+ C left = leftColl ();
118
214
return left != null
119
215
? Either .left (left )
120
216
: Either .right (right == null ? List .of () : right );
121
217
}
122
218
}
123
219
124
- private static class ShortcuttingAcc <L , R > extends Acc <L , L , R > {
220
+ private static final class FirstFailureAcc <L , R > extends Acc <L , L , R > {
125
221
L left ;
126
222
127
223
@ Override
128
224
void combineLeft (L otherLeft ) {
129
225
addLeft (otherLeft );
130
226
}
131
227
228
+ @ Override
132
229
void addLeft (L value ) {
133
230
if (left == null ) {
134
231
left = value ;
135
232
}
136
233
}
137
234
138
- L left () {
235
+ L leftColl () {
139
236
return left ;
140
237
}
141
238
}
142
239
143
- private static class FullAcc <L , R > extends Acc <L , List <L >, R > {
240
+ private static final class AllFailuresAcc <L , R > extends Acc <L , List <L >, R > {
144
241
List <L > left ;
145
242
146
243
@ Override
@@ -152,6 +249,7 @@ void combineLeft(List<L> otherLeft) {
152
249
}
153
250
}
154
251
252
+ @ Override
155
253
void addLeft (L value ) {
156
254
if (left == null ) {
157
255
left = new ArrayList <>();
@@ -160,101 +258,11 @@ void addLeft(L value) {
160
258
}
161
259
162
260
@ Override
163
- List <L > left () {
261
+ List <L > leftColl () {
164
262
return left ;
165
263
}
166
264
}
167
265
168
- /**
169
- * Returns a {@code Collector} that accumulates the input elements into
170
- * a Right containing all values in the original order,
171
- * but only if there are no Left instances in the stream.
172
- * If the stream does contain a Left instance, it discards the Right instances and
173
- * accumulates a Left instance, which contains the first LHS value in the stream,
174
- * in encounter order.
175
- *
176
- * @param <L> the type of the LHS values in the stream
177
- * @param <R> the type of the RHS values in the stream
178
- * @return a {@code Collector} which collects all the input elements into
179
- * a Right containing all RHS values in the stream, or,
180
- * if an LHS value exists, a Left containing the first LHS value
181
- */
182
- public static <L , R > Collector <Either <? extends L , ? extends R >, ?, Either <L , List <R >>> toValidList () {
183
-
184
- BiConsumer <ShortcuttingAcc <L , R >, Either <? extends L , ? extends R >> accumulate = (acc , either ) ->
185
- either .ifLeftOrElse (acc ::addLeft , acc ::addRight );
186
-
187
- BinaryOperator <ShortcuttingAcc <L , R >> combine = (acc , other ) ->
188
- (ShortcuttingAcc <L , R >) acc .combine (other );
189
-
190
- return new CollectorImpl <>(ShortcuttingAcc ::new , accumulate , combine , ShortcuttingAcc ::finish );
191
- }
192
-
193
- /**
194
- * Returns a {@code Collector} that accumulates the input elements into
195
- * a Right containing all values in the original order,
196
- * but only if there are no Left instances in the stream.
197
- * If the stream does contain a Left instance, it discards the Right instances and
198
- * accumulates a Left containing only the LHS values,
199
- * in encounter order.
200
- *
201
- * @param <L> the type of the LHS values in the stream
202
- * @param <R> the type of the RHS values in the stream
203
- * @return a {@code Collector} which collects all the input elements into
204
- * a Right containing all RHS values in the stream,
205
- * or, if an LHS value exists, a Left containing a nonempty list
206
- * of all LHS values in the stream
207
- */
208
- public static <L , R > Collector <Either <? extends L , ? extends R >, ?, Either <List <L >, List <R >>> toValidListAll () {
209
-
210
- BiConsumer <FullAcc <L , R >, Either <? extends L , ? extends R >> accumulate = (acc , either ) ->
211
- either .ifLeftOrElse (acc ::addLeft , acc ::addRight );
212
-
213
- BinaryOperator <FullAcc <L , R >> combine = (acc , other ) ->
214
- (FullAcc <L , R >) acc .combine (other );
215
-
216
- return new CollectorImpl <>(FullAcc ::new , accumulate , combine , FullAcc ::finish );
217
- }
218
-
219
- /**
220
- * Returns a {@code Collector} that accumulates the input elements into
221
- * a new {@code List}. There are no guarantees on the type, mutability,
222
- * serializability, or thread-safety of the {@code List} returned.
223
- * The resulting list is wrapped in an {@code Optional},
224
- * which is empty if and only if the list is empty.
225
- *
226
- * @see #optionalList(List)
227
- * @param <T> the type of the input elements
228
- * @return a list of the RHS values in the stream,
229
- * or, if an LHS value exists, a nonempty list of all LHS values
230
- */
231
- public static <T > Collector <T , ?, Optional <List <T >>> toOptionalList () {
232
- return Collectors .collectingAndThen (
233
- Collectors .toList (),
234
- Eithers ::optionalList );
235
- }
236
-
237
- /**
238
- * If the provided list is empty, returns an empty {@link Optional}.
239
- * Otherwise, returns an {@code Optional} containing the nonempty
240
- * input list.
241
- *
242
- * <p>Note: The resulting {@code Optional} might be used in a
243
- * {@link Either#filter(Function) filter} or
244
- * {@link Either#filterLeft(Function) filterLeft} operation.
245
- *
246
- * @see #toOptionalList()
247
- * @param values a list of objects
248
- * @param <T> the type of the members of {@code values}
249
- * @return an {@code Optional} which is either empty, or
250
- * contains a nonempty list
251
- */
252
- public static <T > Optional <List <T >> optionalList (List <? extends T > values ) {
253
- if (values .isEmpty ()) {
254
- return Optional .empty ();
255
- }
256
- @ SuppressWarnings ("unchecked" )
257
- List <T > result = (List <T >) values ;
258
- return Optional .of (result );
266
+ private Eithers () {
259
267
}
260
268
}
0 commit comments