fastutil 实战指南:用原始类型集合把性能“薅满”

news/2025/11/7 13:44:57/文章来源:https://www.cnblogs.com/databank/p/19199464

当你在 Java 里用 `Map<Integer, Double>`、`Set<Long>`、`List<Integer>` 处理大数据,会被装箱/拆箱与对象头开销“慢到怀疑人生”。fastutil 针对每种原始类型提供成套集合与工具(int/long/double…),直接存取原始值,通常能显著降低内存占用和 GC 压力,并提升吞吐。

为什么选 fastutil
- 原始类型专用集合(如 `Int2ObjectMap`、`IntOpenHashSet`、`IntArrayList`),避免装箱。
- 更丰富的变体(保持插入顺序、定制哈希/等价、支持超大规模 “Big” 容器)。
- 辅助 I/O、迭代器、分割器工具,面向大文件与并行处理。

安装

Maven:
```xml
<dependency>
<groupId>it.unimi.dsi</groupId>
<artifactId>fastutil</artifactId>
<version>8.5.12</version> <!-- 替换为实际最新 -->
</dependency>
```
Gradle:
```gradle
implementation("it.unimi.dsi:fastutil:8.5.12")
```

关键概念(读我先)

- 默认返回值 defaultReturnValue:原始类型 `Map` 的 `get(k)` 返回“默认值”(默认是 0/false)。用 `containsKey(k)` 判断键是否存在;或自定义默认值避坑。
- 装载因子与容量:开放定址哈希(OpenHash)构造可设 `(expectedSize, loadFactor)`,负载低=更快但更占内存。
- 顺序:`LinkedOpenHash*` 保插入顺序;树结构按排序;普通 `OpenHash*` 不保序。
- 线程安全:默认非线程安全;用 `IntCollections.synchronize(x)` 获得同步包装;高并发建议分片或外部锁。
- “Big” 容器:突破 `int` 索引上限,单容器存 2^31+ 元素,通过分段二维数组实现。

常用集合详解与实战示例

1) Int2ObjectOpenHashMap:用 int 做键的高性能映射
- **用途**:图算法(邻接表)、用户 ID → 聚合对象、稠密 ID 映射。
- **要点**:开放定址哈希,摊销 O(1);可设默认返回值;注意存在性判断。

示例:构建邻接表(int 节点 → 邻居列表)

import it.unimi.dsi.fastutil.ints.*;Int2ObjectOpenHashMap<IntArrayList> graph = new Int2ObjectOpenHashMap<>(1 << 20, 0.75f);
graph.defaultReturnValue(null);void addEdge(int u, int v) {
IntArrayList adj = graph.get(u);
if (adj == null) {
adj = new IntArrayList(4);
graph.put(u, adj);
}
adj.add(v);
}

高效遍历条目:

for (Int2ObjectMap.Entry e : graph.int2ObjectEntrySet()) {
int u = e.getIntKey();
IntArrayList adj = e.getValue();
// 处理 u 的邻居
}

设置更易辨识的默认值(如 null)来区分“缺失”:

graph.defaultReturnValue(null);
IntArrayList list = graph.get(7);
if (list == null) { /* 不存在 */ }

2) Object2IntOpenHashMap:对象键 → int 值(计数器的“神兵利器”)
- **用途**:词频统计、类别/ID 编码、对象到稠密索引。
- **优势**:无装箱的 int 值;提供 `addTo(key, delta)` 便捷累加。

示例:词频统计

import it.unimi.dsi.fastutil.objects.*;Object2IntOpenHashMap<String> freq = new Object2IntOpenHashMap<>(1 << 18);
freq.defaultReturnValue(0);void addWord(String w) {
freq.addTo(w, 1); // 不存在则从 0 开始加 1
}int count = freq.getInt("hello"); // 直接取 int

遍历(无装箱):

for (Object2IntMap.Entry<String> e : freq.object2IntEntrySet()) {
String word = e.getKey();
int c = e.getIntValue();
}

3) IntOpenHashSet:原始 int 集合(去重/成员查询)
- **用途**:ID 去重、布隆后备集合、过滤。
- **要点**:摊销 O(1) `add`/`contains`;比 `HashSet<Integer>` 更省内存。

示例:快速去重

import it.unimi.dsi.fastutil.ints.*;IntOpenHashSet seen = new IntOpenHashSet(1 << 20);
if (!seen.contains(uid)) seen.add(uid);

4) IntArrayList:高吞吐动态数组
- **用途**:批量收集、随机访问、需排序的序列。
- **API**:`add`, `getInt`, `set`, `ensureCapacity`, `trim`,以及 `IntArrays` 辅助算法。

示例:构建、排序、去重

import it.unimi.dsi.fastutil.ints.*;IntArrayList arr = new IntArrayList(1 << 20);
arr.add(5); arr.add(3); arr.add(5); arr.add(1);// 就地排序(原始类型快速排序)
IntArrays.quickSort(arr.elements(), 0, arr.size());// 去重输出
int last = Integer.MIN_VALUE;
for (IntIterator it = arr.iterator(); it.hasNext();) {
int x = it.nextInt();
if (x != last) {
// 处理去重后的 x
last = x;
}
}

减少扩容抖动:

arr.ensureCapacity(10_000_000);
// ... 批量 add ...
arr.trim(); // 释放多余容量

5) Int2IntOpenHashMap:int → int 的计数/映射
- **用途**:计数器、离散化映射、双射索引的一侧。
- **技巧**:自定义默认值避免歧义;常配 `addTo` 或手动累加。

示例:计数器(手动累加)

import it.unimi.dsi.fastutil.ints.*;Int2IntOpenHashMap counter = new Int2IntOpenHashMap(1 << 20);
counter.defaultReturnValue(0);void inc(int k) {
counter.put(k, counter.get(k) + 1);
}

6) Int2ObjectLinkedOpenHashMap:保持插入顺序的哈希映射
- **用途**:既要 O(1) 操作,又要稳定迭代顺序(如导出、日志回放)。
- **特性**:在开放定址哈希上叠加双向链,迭代顺序为插入顺序。

示例:稳定地写出键值对

import it.unimi.dsi.fastutil.ints.*;Int2ObjectLinkedOpenHashMap<String> m = new Int2ObjectLinkedOpenHashMap<>();
m.put(2, "b"); m.put(1, "a"); m.put(3, "c");for (Int2ObjectMap.Entry e : m.int2ObjectEntrySet()) {
// 输出顺序:2, 1, 3
}

7) Int2DoubleRBTreeMap / AVLTreeMap:有序映射与范围查询
- **用途**:需要排序、范围视图 `subMap/headMap/tailMap`、就地区间遍历。
- **对比**:AVL 查更快、变更稍慢;红黑树变更更省旋转。

示例:区间统计

import it.unimi.dsi.fastutil.ints.*;Int2DoubleRBTreeMap tm = new Int2DoubleRBTreeMap();
tm.put(1, 1.0); tm.put(5, 5.0); tm.put(9, 9.0);// 半开区间 [from, to)
for (Int2DoubleMap.Entry e : tm.subMap(2, 9).int2DoubleEntrySet()) {
int k = e.getIntKey();
double v = e.getDoubleValue();
}

8) 队列与堆:IntArrayFIFOQueue / IntHeapPriorityQueue
- **用途**:BFS(FIFO 队列)、最短路径/调度(优先队列)。
- **复杂度**:FIFO O(1);二叉堆插入/删除极值 O(log n)。

示例:最小堆

import it.unimi.dsi.fastutil.ints.*;IntHeapPriorityQueue pq = new IntHeapPriorityQueue();
pq.enqueue(7); pq.enqueue(3); pq.enqueue(5);
int top = pq.dequeueInt(); // 3

若需频繁“减小键值”(如 Dijkstra),可考虑 `IntIndirectHeapPriorityQueue`(队列内存索引,键在外部数组上)。

---

9) “Big” 集合与 I/O:超大数据集的读写
- **BigList / BigArrays**:突破 2^31 限制(采用分段数组)。
- **BinIO / TextIO**:批量读写原始数组/集合,面向大文件。

示例:批量写读二进制

import it.unimi.dsi.fastutil.io.*;
import java.io.File;int[] a = new int[1 << 20];
// ... 填充 a ...
BinIO.storeInts(a, new File("ints.bin"));int[] b = BinIO.loadInts("ints.bin");

性能与内存实践清单
- 预估容量优先:构造 `new IntOpenHashSet(expected, 0.75f)`,避免多次 rehash。
- 小集合用数组变体:`IntArraySet`/`Int2ObjectArrayMap`,n≤几千常胜于哈希。
- 顺序需求:用 `LinkedOpenHash*` 而非普通 `OpenHash*`。
- 避免歧义:设置 `defaultReturnValue(-1)` 或 `null`,并用 `containsKey` 判存在。
- 批量场景:`ensureCapacity` + 最后 `trim`,减少扩容与峰值内存。
- 浮点键:注意 `NaN`、`+0.0/-0.0`;若需特殊相等性,用 `...OpenCustomHash...` 搭配 `Strategy`。
- 遍历取原始值:优先 `getInt`/`getLong` 等专用方法与特化迭代器,避免装箱。
- 线程场景:读多写少用同步包装;高并发用分片/分段锁或无锁汇聚后合并。

---

与 JDK 集合的互操作
- 大多实现 `java.util` 接口,能与现有代码协作。
- 工具类提供只读/同步包装与空/单例集合(如 `IntCollections.unmodifiable(list)`、`IntSets.singleton(x)`)。
- 需要与 JDK Stream 协作时,可通过 `spliterator` 或桥接。

---

适用场景速配
- 计数/频率统计:`Object2IntOpenHashMap`(用 `addTo`)。
- 稠密 ID → 对象:`Int2ObjectOpenHashMap`。
- 去重/过滤:`IntOpenHashSet`。
- 高吞吐序列:`IntArrayList` + `IntArrays.quickSort`。
- 有序/区间:`Int2DoubleRBTreeMap`(或 AVL)。
- 稀疏但顺序稳定:`Int2ObjectLinkedOpenHashMap`。
- 超大规模:`LongBigArrayBigList`、`ObjectBigArrayBigList` + `BinIO`。

参考与主页:[fastutil 官方站点](https://fastutil.di.unimi.it/)(文档与 API 列表)

---

结语
如果你正用 `HashMap<Integer, ?>`、`HashSet<Long>` 处理中大规模数据,迁移到 fastutil 常能带来可观的内存与速度改善。优先替换热点路径的集合类型,并结合上面的容量规划、默认值与遍历技巧,通常即可拿到“零业务改动”的性能红利。

- 如需,我可以根据你的业务数据规模与访问模式,给出定制选型与 API 最小示例。

- 也可把你现有的 JDK 集合用法贴过来,我帮你逐一替换为等价的 fastutil 实现与代码片段。

- - -

- 这篇文章概述 fastutil 的动机、关键概念、以及 8 类常用集合(含 `Int2ObjectOpenHashMap`、`Object2IntOpenHashMap`、`IntOpenHashSet`、`IntArrayList`、`Int2IntOpenHashMap`、`Int2ObjectLinkedOpenHashMap`、`Int2DoubleRBTreeMap`、优先队列)的特性与示例。
- 提供了“Big+I/O”用法与一份高频实践清单,便于直接落地。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/958777.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在关闭浏览器标签前,可靠地发送 HTTP 请求? - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Python 必背内置函数

一、输出与输入类 print() : 打印输出给定内容。示例:print("Hello, Python!") #输出 Hello, Python!input() :接收用户输入并返回字符串。示例:age = input("请输入年龄:") 输入 18 后, ag…

实用指南:【Java并发】深入理解synchronized

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年发电机厂家权威推荐榜:柴油发电机组/康明斯/玉柴/高压/大功率发电机,专业选购指南与实力解析

一、行业背景与发展趋势随着我国工业化进程的加速推进,发电设备行业作为国民经济的重要基础产业,正迎来新一轮发展机遇。特别是在"双碳"目标背景下,发电机组行业正朝着高效节能、智能控制、环保低碳的方向…

2025年磷酸氢二钾定制厂家权威推荐榜单:磷酸氢二钠/磷酸二氢钠/磷酸源头厂家精选

在食品加工、医药制造与工业水处理等领域,磷酸氢二钾及其相关磷酸盐作为重要的功能添加剂与化学中间体,其质量稳定性与定制化服务能力已成为下游用户的核心关注点。行业数据显示,2024年中国磷酸盐市场规模已突破200…

P2P CDN Tracker 技术深度解析(三):会话管理与心跳机制

在支持100万+并发连接的P2P系统中,如何高效管理用户会话、及时检测失效连接、合理回收资源?本文深入剖析Tracker的"生命线"——会话管理与心跳机制。前情回顾 在第1篇中,我们了解了Tracker的整体架构;第…

2025年发电机厂家推荐排行榜,发电机组,柴油发电机组,康明斯发电机,玉柴发电机,高压发电机,大功率发电机公司精选

一、行业背景与发展趋势随着全球能源转型加速和电力需求持续增长,发电设备行业正迎来新一轮技术变革。在工业制造、数据中心、医疗设施、商业建筑等领域,发电机组作为重要的备用电源和主力电源,其技术水平和产品质量…

Modbus Tcp协议

Modbus Tcp协议Posted on 2025-11-07 13:35 懒得理 阅读(0) 评论(0) 收藏 举报⚠️RX 最后的 4/N 个数据字节(xx xx xx xx / xx xx xx xx)是举例的伪数据, 实际内容由设备当前状态决定。 [1]读取输出线圈 功能…

高频电流探头在电源质量与谐波分析中的应用

在现代电力系统中,电源质量对设备运行稳定性、系统能效以及设备寿命有着直接影响。随着非线性负载和电力电子设备的广泛应用,谐波污染、电压波动、三相不平衡等电能质量问题愈发突出。高频电流探头作为关键测量工具,…

抖音 独立 IP 解决方案:独享静态住宅 IP + 环境隔离 + 粘性会话 - Smart

面向矩阵与品牌运营的全球覆盖、低延迟与可观测性基线方案 [1] 核心优势 8000 万+ 真实住宅 IP 资源池,覆盖全球 200+ 国家/地区,支持城市级精准定位 [1] 独享静态住宅 IP,一账号一环境,长时会话稳定不中断 [1] 低…

Cursor 2.0 扩展 Composer 功能,助力上下文感知式开发 - 公众号

本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续!🚀 魔都架构师 | 全网30W技术追随者 🔧 大厂分布式系统/数据中台实战专家 🏆 主导交易系统百万级流量调优 & 车联网平台架构 🧠 AIGC应用…

[论文阅读] AI+教学 | 编程入门课的AI助手革命?ChatGPT的4大核心影响全解析 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

MySQL——表的管理

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

【传奇开心果系列】基于Flet框架实现的分析题型的掌握程度不同题型得分饼图样式示例自定义模板特色和完成原理深度解析

【传奇开心果系列】基于Flet框架实现的分析题型的掌握程度不同题型得分饼图样式示例自定义模板特色和完成原理深度解析pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !importan…

Linux命令总览

yum yumdownloader --resolve --destdir=/wise nginx --resolve 下载软件包及所有依赖 rpm sudo rpm -ivh *.rpm -i:install 的缩写,表示安装软件包。 -v:verbose 的缩写,显示安装过程的详细信息。 -h:hash 的缩写…

量化选股与量化交易第819篇:大单短线量化指标公式 - Leone

大单短线量化指标是一个用于筛选可能具有短线妖股特征的股票的综合指标。该指标结合了多个因素,包括20日涨跌幅、流通市值、换手率以及当日振幅,通过综合评分来判断股票是否可能成为妖股。 1、20日涨跌幅:计算股票在…

【MySQL】SQL调优-如何分析SQL性能 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

asp.net网站编译后出现“发现不明确的匹配”的错误

asp.net网站编译后出现“发现不明确的匹配”的错误参考文章——asp.net系统发布后,报错 :Ambiguous match found. 解决办法 没想到asp.net编译后,变量竟然没有区分大小写。

量化选股与量化交易第820篇:趋势突破K线均线平台指标公式 - Leone

趋势突破K线均线平台指标简介 一、核心指标: 1、MA25:25日简单移动平均线,用于平滑股价数据,反映中期趋势。 2、EMA135:135日指数移动平均线,对价格变化更为敏感,用于捕捉长期趋势。 3、EMA250:250日指数移动平均线…

Docker 部署 Oracle Linux 实操全流程

Oracle Linux 不只是普通的 RHEL 兼容发行版,更是经过 Oracle 每日超 12 万小时工作负载测试的企业级系统,自带 Ksplice(零停机内核补丁)、DTrace(实时诊断)等独家功能,尤其适合搭配 Oracle 数据库、中间件等生…