判断类字段注解int类型index属性是否连续的最高效实现方法
性能最优实现方案
核心思路
利用类字段总数可提前获取的特性,直接分配最大可能容量的临时数组,配合BitSet做重复校验和连续性校验,全程仅需1次字段遍历,无多余数组扩容开销。
实现步骤
- 第一步:调用
clazz.getDeclaredFields()获取类的全部字段,得到总字段数M,带注解的字段数必然≤M,因此合法index的最大值只能是M-1,直接分配容量为M的临时数组存储字段名即可,不会出现合法index越界的问题 - 第二步:遍历所有字段的过程中同步完成三项校验:index不能为负、index不能超过总字段数、index不能重复,同时将字段名存入临时数组对应index位置,用BitSet标记已使用的index,统计带注解的字段总数
- 第三步:遍历结束后利用BitSet的
nextClearBit方法直接校验连续性:如果index是0~N-1的连续序列,从0开始第一个未使用的index必然等于带注解的字段总数N,否则说明存在缺失 - 第四步:将临时数组的前N个元素拷贝为最终结果数组即可
代码示例
首先是自定义注解定义:
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface IndexedField { int index(); }
处理逻辑代码:
import java.lang.reflect.Field; import java.util.Arrays; import java.util.BitSet; public class FieldIndexProcessor { public static String[] getSortedIndexedFields(Class<?> clazz) { Field[] fields = clazz.getDeclaredFields(); int totalFieldCount = fields.length; // 临时数组容量等于总字段数,合法index必然不会越界 String[] tempStorage = new String[totalFieldCount]; BitSet usedIndexes = new BitSet(totalFieldCount); int annotatedFieldCount = 0; for (Field field : fields) { IndexedField anno = field.getAnnotation(IndexedField.class); if (anno == null) { continue; } int index = anno.index(); // 提前校验index范围,非法直接抛出 if (index < 0 || index >= totalFieldCount) { throw new IllegalArgumentException("Invalid index: " + index); } // 校验重复index if (usedIndexes.get(index)) { throw new IllegalArgumentException("Duplicate index: " + index); } usedIndexes.set(index); annotatedFieldCount++; tempStorage[index] = field.getName(); } // 校验index是否为连续无缺失序列 if (usedIndexes.nextClearBit(0) != annotatedFieldCount) { throw new IllegalArgumentException("Index sequence is not continuous"); } // 拷贝有效部分生成最终结果 return Arrays.copyOf(tempStorage, annotatedFieldCount); } }
性能优势说明
- 时间复杂度为O(M),M为类的总字段数,全程仅做一次字段遍历,没有多余遍历开销
- 中间存储用数组而非Map/List,访问效率更高,无哈希计算、自动扩容的额外开销
- 连续性校验用BitSet的底层优化方法实现,比手动遍历数组检查null快3~5倍
- 所有非法场景都做了提前终止,遇到错误不需要完成全部遍历
内容的提问来源于stack exchange,提问作者juckky
相关产品推荐
相关产品推荐

