"Hacky" solution that only evaluates the first two elements:
.limit(2)
.map(Optional::ofNullable)
.reduce(Optional.empty(),
(a, b) -> a.isPresent() ^ b.isPresent() ? b : Optional.empty());
Some basic explanation:
Single element [1] -> map to [Optional(1)] -> reduce does
"Empty XOR Present" yields Optional(1)
= Optional(1)
Two elements [1, 2] -> map to [Optional(1), Optional(2)] -> reduce does:
"Empty XOR Present" yields Optional(1)
"Optional(1) XOR Optional(2)" yields Optional.Empty
= Optional.Empty
Here is the complete testcase:
public static <T> Optional<T> singleOrEmpty(Stream<T> stream) {
return stream.limit(2)
.map(Optional::ofNullable)
.reduce(Optional.empty(),
(a, b) -> a.isPresent() ^ b.isPresent() ? b : Optional.empty());
}
@Test
public void test() {
testCase(Optional.empty());
testCase(Optional.of(1), 1);
testCase(Optional.empty(), 1, 1);
testCase(Optional.empty(), 1, 1, 1);
}
private void testCase(Optional<Integer> expected, Integer... values) {
Assert.assertEquals(expected, singleOrEmpty(Arrays.stream(values)));
}
Kudos to Ned (the OP) who has contributed the XOR idea and the above testcase!