为何Java中首个Optional+findAny代码返回"withAnyVal"而非null?
问题分析
已知getContacts()返回一个空集合,以下三段代码执行结果存在差异:
var a = Optional.of(new Detail().getContacts()) // Optional<Set<String>> .stream() // Stream<Set<String>> .findAny() // Optional<Set<String>> .map(o -> "withAnyVal") .orElse(null);
var b = Optional.of(new Detail().getContacts()) // Optional<Set<String>> .stream() // Stream<Set<String>> .flatMap(Collection::stream) // Stream<String> .findAny() // Optional<String> .map(o -> "withAnyVal") .orElse(null);
var c = Optional.of(new Detail()) .map(Detail::getContacts) .stream() .flatMap(Collection::stream) .findAny() .map(o -> "withAnyVal") .orElse(null);
问题:为何第一段代码会返回"withAnyVal"?按预期它应该在findAny处匹配失败并执行orElse返回null才对?只有代码b和c返回了正确的null值。
原因解析
核心差异在于空集合本身是一个有效的非null对象,这是关键:
代码a的执行逻辑:
Optional.of(new Detail().getContacts()):因为getContacts()返回的是空集合(不是null),所以这个Optional是存在有效值的,值就是那个空的Set<String>。.stream():把这个Optional转换成包含一个元素的流——这个元素就是空集合。.findAny():流里有一个元素(空集合),所以直接返回包含这个空集合的Optional<Set<String>>,并非空Optional。.map(o -> "withAnyVal"):因为Optional有值,所以执行map操作,返回包含"withAnyVal"的Optional。.orElse(null):Optional存在有效值,直接返回"withAnyVal",不会触发orElse分支。
代码b和c的执行逻辑:
- 两者都调用了
flatMap(Collection::stream):把流里的空集合转换成了空的String流(空集合的stream本身没有元素)。 .findAny():空流中没有元素,所以返回空的Optional。 - 后续的map操作不会执行,直接走到
.orElse(null)分支,返回null。
- 两者都调用了
简单来说,代码a判断的是“是否存在集合对象”,而b和c判断的是“集合里是否有元素”,这是完全不同的两个判断逻辑。
内容的提问来源于stack exchange,提问作者sophie
相关产品推荐
相关产品推荐

