应优先使用longstream处理long数据以避免装箱拆箱:适用于原始long数组、高频数值计算、超10万数据量及压测发现long.valueof()耗时等场景;创建时用longstream.of/range/arrays.stream等直接操作原始类型,聚合用sum/max/average等原生方法,必要时才用boxed()装箱。

用 LongStream 处理 long 类型数据,核心就是绕过 Long 包装类的装箱(int → Integer)和拆箱(Integer → int)过程。Java 的泛型 Stream 无法直接存原始类型,所以 Stream<long></long> 每次操作都要新建对象、触发 GC、增加内存压力;而 LongStream 全程使用 long 原始值,零装箱、零拆箱,对时间戳、ID 序列、计数器等场景提速明显。
什么时候该换用 LongStream
满足以下任一情况,就值得切换:
- 数据源本身就是原始 long 数组或范围(如
long[] ids、System.currentTimeMillis()批量采集) - 做高频数值计算:求和、最大值、平均值、统计摘要(
summaryStatistics()) - 集合规模超过 10 万条,且当前用的是
Stream<long></long>或List<long></long> - 压测发现 CPU 花在
Long.valueOf()或longValue()上(可借助 JFR 或 VisualVM 观察)
创建 LongStream 的常用方式
避免从包装类集合起步,优先从原始结构出发:
-
LongStream.of(1L, 2L, 3L)—— 直接传 long 字面量,不经过 Long 构造 -
LongStream.range(0, 1_000_000)—— 生成左闭右开区间,高效且无对象生成 -
LongStream.rangeClosed(1, 100)—— 含右端点,适合 ID、页码等连续序列 -
Arrays.stream(longArray)—— 对long[]直接切片,比先转List<long></long>再 stream 快 3–5 倍 -
LongStream.generate(() -> System.nanoTime()).limit(1000)—— 需要动态生成时用,注意控制数量防无限流
关键操作别掉回包装类型
一旦进入 Stream<long></long>,前面的优化就白做了。注意这些易错点:
- 不用
.mapToObj(Long::valueOf)转成对象流,除非真要调用Long方法(如toHexString()) - 聚合尽量用原生终端方法:
sum()、max().orElse(-1)、average().orElse(0.0),比.reduce(0L, Long::sum)更快更安全 - 需要转其他原始流时,优先用
.asDoubleStream()或.mapToInt(l -> (int) l)(注意溢出),而非先 boxed 再 map - 真要转对象流再处理?用
.boxed()—— 这是唯一推荐的装箱入口,且只在必要时调用一次
一个对比示例:百万级时间戳求和
低效写法(触发百万次装箱):
List
long total = timestamps.stream().reduce(0L, Long::sum);
高效写法(全程原始类型):
long[] tsArray = getTimestampsAsPrimitiveArray(); // 改为返回 long[]
long total = Arrays.stream(tsArray).sum();
如果只能拿到 List<long></long>,至少提前转原始数组:long[] arr = list.stream().mapToLong(Long::longValue).toArray();,再走 Arrays.stream(arr)。











