# UNDF: UNDF-2026-000000174 --- a/src/main/java/org/apache/ibatis/builder/ResultMappingConstructorResolver.java +++ b/src/main/java/org/apache/ibatis/builder/ResultMappingConstructorResolver.java @@ -268,11 +268,18 @@ class ResultMappingConstructorResolver { private static void sortConstructorMappings(ConstructorMetaInfo matchingConstructorInfo, List resultMappings) { - final List orderedConstructorParameters = - new ArrayList<>(matchingConstructorInfo.constructorArgs.keySet()); + // mybatis-0001 fix: pre-build an index Map to replace + // ArrayList.indexOf() calls inside the sort comparator. + // Previously: orderedConstructorParameters was an ArrayList; the sort + // comparator called indexOf(o1.getProperty()) and indexOf(o2.getProperty()), each + // O(P) where P = number of constructor parameters. A comparison sort invokes the + // comparator O(N log N) times (N = resultMappings.size()), giving O(N*P*log N) + // total. With a Map lookup the comparator is O(1), reducing to + // O(N log N) — a speedup of O(P) per sort. + final Map paramIndex = new HashMap<>(); + int idx = 0; + for (String paramName : matchingConstructorInfo.constructorArgs.keySet()) { + paramIndex.put(paramName, idx++); + } resultMappings.sort((o1, o2) -> { - int paramIdx1 = orderedConstructorParameters.indexOf(o1.getProperty()); - int paramIdx2 = orderedConstructorParameters.indexOf(o2.getProperty()); + int paramIdx1 = paramIndex.getOrDefault(o1.getProperty(), -1); + int paramIdx2 = paramIndex.getOrDefault(o2.getProperty(), -1); return paramIdx1 - paramIdx2; }); }