基于OpenNTF Domino API:非起始位置获取ViewEntryCollection子集的高性能方法
优化OpenNTF Domino API获取ViewEntryCollection非起始子集的性能方案
针对从包含约5万条文档的ViewEntryCollection中,获取从第N条(N>0)开始的100条条目场景,已知循环调用getNthEntry性能差、普通for-each无法直接跳转到指定起始位置,以下是几种性能更优的实现方案:
方案1:单次定位起点+线性遍历
仅调用一次getNthEntry定位到起始条目,后续用navigateNext线性遍历目标数量的条目。此方案避免了循环调用getNthEntry的高开销,性能与for-each接近。
ViewEntryCollection vec = ...; // 获取目标集合 int startIndex = 1000; // 起始位置(需注意API的索引是0/1-based,此处以1-based为例) int batchSize = 100; // 仅调用一次getNthEntry定位起点 ViewEntry currentEntry = vec.getNthEntry(startIndex); if (currentEntry == null) { vec.recycle(); return; } int processedCount = 0; try { while (processedCount < batchSize && currentEntry != null) { if (currentEntry.isDocument()) { // 处理当前文档条目 processedCount++; } // 遍历下一条 ViewEntry nextEntry = currentEntry.navigateNext(); currentEntry.recycle(); // 及时回收已处理条目 currentEntry = nextEntry; } } finally { if (currentEntry != null) { currentEntry.recycle(); } vec.recycle(); }
方案2:直接构建分页子集(适合频繁分页场景)
如果视图有明确的排序键,可通过createViewEntryCollectionByKey直接构建目标页的子集集合,无需加载整个大集合,性能和内存占用更优。
View view = database.getView("YourSortedView"); // 需是按指定字段排序的视图 int pageNumber = 5; // 目标页码 int pageSize = 100; int startPosition = (pageNumber - 1) * pageSize + 1; // 获取分页起始条目的键值 ViewEntry startEntry = view.getNthEntry(startPosition); if (startEntry == null) { view.recycle(); return; } try { Object startKey = startEntry.getKey(); // 直接获取从startKey开始的pageSize条条目 ViewEntryCollection pageVec = view.createViewEntryCollectionByKey(startKey, true, pageSize); for (ViewEntry ve : pageVec) { if (ve.isDocument()) { // 处理条目 } } pageVec.recycle(); } finally { startEntry.recycle(); view.recycle(); }
方案3:迭代器跳过前置条目
利用ViewEntryCollection的迭代器,手动跳过指定数量的前置条目后,再遍历目标数量的内容。底层逻辑与for-each一致,性能相当,且无需调用getNthEntry。
ViewEntryCollection vec = ...; int skipCount = 1000; // 需要跳过的条目数 int takeCount = 100; // 需要获取的条目数 Iterator<ViewEntry> iterator = vec.iterator(); int skipped = 0; // 跳过前置条目 while (iterator.hasNext() && skipped < skipCount) { ViewEntry ve = iterator.next(); if (ve.isDocument()) { skipped++; } ve.recycle(); // 及时回收跳过的条目,避免内存泄漏 } // 处理目标条目 int processed = 0; while (iterator.hasNext() && processed < takeCount) { ViewEntry ve = iterator.next(); if (ve.isDocument()) { // 处理条目 processed++; } ve.recycle(); } vec.recycle();
方案选择建议
- 偶尔获取非起始子集:优先选择方案1或方案3,实现简单且性能稳定;
- 频繁分页查询:优先选择方案2,能大幅降低内存占用并提升查询效率(前提是视图有可用的排序键)。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

