OptionalInt和OptionalLong是专为int、long设计的无装箱、低GC开销空值容器,仅用于数值流(如IntStream.max())返回场景,不支持filter/map等链式操作,取值须用orElse或ifPresent,不可与Optional混用。

Java 中的 OptionalInt 和 OptionalLong 是专为基本类型 int 和 long 设计的空值容器,不装箱、无 GC 开销,适用于数值流处理和性能敏感场景。它们不是 Optional 或 Optional 的替代品,而是语义与性能都不同的独立类型。
什么时候必须用 OptionalInt/OptionalLong
当你从原生数值流(如 IntStream、LongStream)中调用可能无结果的操作时,JDK 强制返回对应原生 Optional:
-
IntStream.of(1, 2, 3).max()→ 返回OptionalInt,不是Optional -
LongStream.empty().findFirst()→ 返回OptionalLong.empty() - 混用会编译失败:不能把
OptionalLong直接赋给Optional,也不能用.get()(它没有这个方法)
怎么安全取值,避免踩坑
它们不提供 get(),只提供 getAsInt() / getAsLong() —— 但直接调用会在空值时报 NoSuchElementException。推荐以下方式:
- 用
orElse(0)提供默认值(注意:0 是合法值,不能用来反推“是否为空”) - 用
orElseGet(() -> computeDefault())延迟计算默认值,适合开销大的场景 - 用
ifPresent(value -> {...})安全消费值,不触发异常 - 需要转成引用类型时,显式调用
.mapToObj(Integer::valueOf)或.mapToObj(Long::valueOf)
不能做什么,容易出错的地方
这些原生 Optional 功能比 Optional 更精简,刻意舍弃了部分 API 来保证轻量:
- 没有
ofNullable()—— 因为基本类型本身不能为null,所以只提供of(value)和empty() - 不支持
filter()、map()、flatMap()—— 想链式转换必须先转成引用类型再操作 - 不能用
== null判断,也不能用isPresent() && value == 0来等价于“空”,因为 0L 是有效业务值(比如时间戳零点)
和包装类 Optional 的选择建议
日常变量判空或通用空值建模,优先用 Optional;只有在以下情况才选 OptionalLong:
- 处理
LongStream的聚合结果(max()、min()、average()等) - 对 GC 敏感、高频创建/销毁的数值空值场景(如实时指标统计)
- 明确要表达“这是一个原生 long,且可能不存在”,而非“一个可能为 null 的 Long 对象”










