1717package com .google .common .collect ;
1818
1919import static com .google .common .base .Preconditions .checkNotNull ;
20+ import static com .google .common .collect .NullnessCasts .uncheckedCastNullableTToT ;
2021import static java .util .Collections .emptyList ;
2122
2223import com .google .common .annotations .GwtCompatible ;
2324import java .util .ArrayList ;
2425import java .util .List ;
2526import java .util .NoSuchElementException ;
2627import java .util .Optional ;
28+ import java .util .function .Supplier ;
2729import java .util .stream .Collector ;
2830import org .jspecify .annotations .Nullable ;
2931
@@ -44,7 +46,7 @@ public final class MoreCollectors {
4446 */
4547 private static final Collector <Object , ?, Optional <Object >> TO_OPTIONAL =
4648 Collector .of (
47- ToOptionalState :: new ,
49+ () -> new ToOptionalState <>( null ) ,
4850 ToOptionalState ::add ,
4951 ToOptionalState ::combine ,
5052 ToOptionalState ::getOptional ,
@@ -66,8 +68,8 @@ public final class MoreCollectors {
6668 private static final Object NULL_PLACEHOLDER = new Object ();
6769
6870 private static final Collector <@ Nullable Object , ?, @ Nullable Object > ONLY_ELEMENT =
69- Collector .<@ Nullable Object , ToOptionalState , @ Nullable Object >of (
70- ToOptionalState :: new ,
71+ Collector .<@ Nullable Object , ToOptionalState < Object > , @ Nullable Object >of (
72+ () -> new ToOptionalState <>( null ) ,
7173 (state , o ) -> state .add ((o == null ) ? NULL_PLACEHOLDER : o ),
7274 ToOptionalState ::combine ,
7375 state -> {
@@ -91,18 +93,24 @@ public final class MoreCollectors {
9193 * than one, not just two.
9294 */
9395 @ SuppressWarnings ("EmptyList" ) // ImmutableList doesn't support nullable element types
94- private static final class ToOptionalState {
96+ @ IgnoreJRERequirement // see enclosing class (whose annotation Animal Sniffer ignores here...)
97+ private static final class ToOptionalState <T > {
9598 static final int MAX_EXTRAS = 4 ;
9699
97- @ Nullable Object element ;
98- List <Object > extras ;
100+ @ Nullable T element ;
101+ List <T > extras ;
102+ final @ Nullable Supplier <? extends RuntimeException > exceptionSupplier ;
99103
100- ToOptionalState () {
101- element = null ;
102- extras = emptyList ();
104+ ToOptionalState (@ Nullable Supplier <? extends RuntimeException > exceptionSupplier ) {
105+ this .element = null ;
106+ this .extras = emptyList ();
107+ this .exceptionSupplier = exceptionSupplier ;
103108 }
104109
105- IllegalArgumentException multiples (boolean overflow ) {
110+ RuntimeException multiples (boolean overflow ) {
111+ if (exceptionSupplier != null ) {
112+ throw exceptionSupplier .get ();
113+ }
106114 StringBuilder sb =
107115 new StringBuilder ().append ("expected one element but was: <" ).append (element );
108116 for (Object o : extras ) {
@@ -115,7 +123,7 @@ IllegalArgumentException multiples(boolean overflow) {
115123 throw new IllegalArgumentException (sb .toString ());
116124 }
117125
118- void add (Object o ) {
126+ void add (T o ) {
119127 checkNotNull (o );
120128 if (element == null ) {
121129 this .element = o ;
@@ -130,7 +138,7 @@ void add(Object o) {
130138 }
131139 }
132140
133- ToOptionalState combine (ToOptionalState other ) {
141+ ToOptionalState < T > combine (ToOptionalState < T > other ) {
134142 if (element == null ) {
135143 return other ;
136144 } else if (other .element == null ) {
@@ -151,19 +159,23 @@ ToOptionalState combine(ToOptionalState other) {
151159 }
152160
153161 @ IgnoreJRERequirement // see enclosing class (whose annotation Animal Sniffer ignores here...)
154- Optional <Object > getOptional () {
162+ Optional <T > getOptional () {
155163 if (extras .isEmpty ()) {
156164 return Optional .ofNullable (element );
157165 } else {
158166 throw multiples (false );
159167 }
160168 }
161169
162- Object getElement () {
170+ T getElement () {
163171 if (element == null ) {
164- throw new NoSuchElementException ();
172+ if (exceptionSupplier != null ) {
173+ throw exceptionSupplier .get ();
174+ } else {
175+ throw new NoSuchElementException ();
176+ }
165177 } else if (extras .isEmpty ()) {
166- return element ;
178+ return uncheckedCastNullableTToT ( element ) ;
167179 } else {
168180 throw multiples (false );
169181 }
0 commit comments