Using Java streams and generics I'm trying to create a Collector, that would return me Optional.empty, if stream is empty, Optional<T> if stream has one item and throw exception if stream has more than one item.
public static <T, R extends Optional<T>> Collector<T, ?, R> toOptional() {
return Collectors.collectingAndThen(
Collectors.toList(),
list -> {
if (list.size() > 1) {
throw new CollectingException("More than one item found in: " + list);
}
if (list.size() == 1) {
return Optional.of(list.get(0));
}
return Optional.empty();
}
);
}
However I'm getting an error I don't understand.
Required type:
Collector<T,?,R>
Provided:
Collector<Object,Object,Object>
no instance(s) of type variable(s) T exist so that Optional<T> conforms to R inference variable RR has incompatible bounds: equality constraints: R lower bounds: Optional<T1868063>
The desired usage would be
List<Person> people = new ArrayList<>();
Optional<Person> john = people.stream().filter(person->"John".equals(person.getName())).collect(toOptional());
Could anyone please explain me what's wrong?
This answer does already tell you how to declare the method correctly.
However, note that you don’t need this special collector. You can simply use
Collectors.reducing((first, second) -> {
throw new CollectingException("More than one item found, "
+ "first: " + first + ", second: " + second);
})
which does already your intended job. (see Collectors.reducing(…))
Optional is returnedOptional containing the element is returnedList first but directly produces the Optional.List but stops when encountering the second element.When you don’t want to combine this logic with other collectors, you don’t need a collector at all but can use reduce on the Stream directly:
List<Person> people = new ArrayList<>();
Optional<Person> john = people.stream()
.filter(person -> "John".equals(person.getName()))
.reduce((first, second) -> {
throw new CollectingException("More than one item found, "
+ "first: " + first + ", second: " + second);
});
does the same as
Optional<Person> john = people.stream()
.filter(person -> "John".equals(person.getName()))
.collect(Collectors.reducing((first, second) -> {
throw new CollectingException("More than one item found, "
+ "first: " + first + ", second: " + second);
}));
The declaration of your method is not correct, instead of:
public static <T, R extends Optional<T>> Collector<T, ?, R> toOptional() {
You can just use:
public static <T> Collector<T, ?, Optional<T>> toOptional() {
In other words, the method need to return an Optional object of type T directly, instead of using a separate type parameter R that extends Optional<T>.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With