{"record":{"id":"4523c6c012d2eb4c","repo":"chinabugotech/hutool","slug":"comparator-ordering-cannot-be-changed-after-the-fi","errorCode":null,"errorMessage":"Comparator ordering cannot be changed after the first comparison is performed","messagePattern":"Comparator ordering cannot be changed after the first comparison is performed","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hutool-core/src/main/java/cn/hutool/core/comparator/ComparatorChain.java","lineNumber":341,"sourceCode":"\t\tif (object.getClass().equals(this.getClass())) {\n\t\t\tfinal ComparatorChain<?> otherChain = (ComparatorChain<?>) object;\n\t\t\t//\n\t\t\treturn Objects.equals(this.orderingBits, otherChain.orderingBits)\n\t\t\t\t\t&& this.chain.equals(otherChain.chain);\n\t\t}\n\t\treturn false;\n\t}\n\n\t//------------------------------------------------------------------------------------------------------------------------------- Private method start\n\n\t/**\n\t * 被锁定时抛出异常\n\t *\n\t * @throws UnsupportedOperationException 被锁定抛出此异常\n\t */\n\tprivate void checkLocked() {\n\t\tif (lock == true) {\n\t\t\tthrow new UnsupportedOperationException(\"Comparator ordering cannot be changed after the first comparison is performed\");\n\t\t}\n\t}\n\n\t/**\n\t * 检查比较器链是否为空，为空抛出异常\n\t *\n\t * @throws UnsupportedOperationException 为空抛出此异常\n\t */\n\tprivate void checkChainIntegrity() {\n\t\tif (chain.size() == 0) {\n\t\t\tthrow new UnsupportedOperationException(\"ComparatorChains must contain at least one Comparator\");\n\t\t}\n\t}\n\t//------------------------------------------------------------------------------------------------------------------------------- Private method start\n}\n","sourceCodeStart":323,"sourceCodeEnd":357,"githubUrl":"https://github.com/chinabugotech/hutool/blob/8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442/hutool-core/src/main/java/cn/hutool/core/comparator/ComparatorChain.java#L323-L357","documentation":"Thrown by ComparatorChain when attempting to modify the chain (addComparator, setComparator, setForwardSort, setReverseSort) after the first call to compare(). The chain 'locks' itself on the first comparison to ensure consistent ordering throughout a sort operation. This is a state-transition error: the object transitions from mutable to immutable after first use.","triggerScenarios":"Calling chain.addComparator(...), chain.setComparator(...), chain.setForwardSort(...), or chain.setReverseSort(...) after chain.compare(a, b) has been called at least once. The lock flag is set to true on the first compare() invocation and checkLocked() is called by every mutator method.","commonSituations":"Reusing a ComparatorChain instance across multiple sort operations and trying to modify it between sorts. Building a chain lazily but starting to compare before construction is complete. Sharing a chain instance across threads where one thread compares while another modifies.","solutions":["Complete all addComparator/setComparator/setForwardSort/setReverseSort calls before the first compare() invocation.","Create a new ComparatorChain instance if you need a different ordering after comparisons have started.","Use the static factory methods (ComparatorChain.of(...)) to build a fully-configured chain in one step.","Check chain.isLocked() before attempting modifications."],"exampleFix":"// before\nComparatorChain<String> chain = new ComparatorChain<>(Comparator.naturalOrder());\nCollections.sort(list, chain);\nchain.addComparator(String.CASE_INSENSITIVE_ORDER); // throws — already locked\n\n// after\nComparatorChain<String> chain = ComparatorChain.of(\n    Comparator.naturalOrder(), String.CASE_INSENSITIVE_ORDER\n);\nCollections.sort(list, chain);","handlingStrategy":"validation","validationCode":"if (!chain.isLocked()) {\n    chain.addComparator(newComparator);\n} else {\n    // create a new chain instead\n    throw new IllegalStateException(\"ComparatorChain is locked\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure all comparators before the first compare() call.","Use ComparatorChain.of(...) factory methods for one-step construction.","Check isLocked() before attempting modifications.","Create a new instance rather than modifying a used one."],"tags":["comparator","state-locked","immutable","sort"],"backgroundTag":null,"analyzedSha":"8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442","analyzedAt":"2026-08-14T04:01:12.892Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}