diff --git a/java/java-analysis-impl/src/com/siyeh/ig/migration/ComparatorMinMaxCanBeUsedInspection.java b/java/java-analysis-impl/src/com/siyeh/ig/migration/ComparatorMinMaxCanBeUsedInspection.java index 6a3a2e65cd43..24591a9c43f6 100644 --- a/java/java-analysis-impl/src/com/siyeh/ig/migration/ComparatorMinMaxCanBeUsedInspection.java +++ b/java/java-analysis-impl/src/com/siyeh/ig/migration/ComparatorMinMaxCanBeUsedInspection.java @@ -153,8 +153,11 @@ public final class ComparatorMinMaxCanBeUsedInspection extends BaseInspection { if (!thenIsFirst && !thenIsSecond) return null; String methodName = RelationType.GE.isSubRelation(relationType) == thenIsFirst ? "max" : "min"; + // Need to flip arguments to preserve the semantics precisely if equality is not included into condition, + // as for equal `a` and `b`, `compare(a, b) > 0 ? a : b` returns `b` while `max(a, b)` return `a`. + boolean flip = !relationType.isSubRelation(RelationType.EQ); - return new MinMaxInfo(qualifier, args[0], args[1], methodName); + return new MinMaxInfo(qualifier, args[flip ? 1 : 0], args[flip ? 0 : 1], methodName); } private static class ComparatorMinMaxVisitor extends BaseInspectionVisitor { diff --git a/java/java-impl/resources/inspectionDescriptions/ComparatorMinMaxCanBeUsed.html b/java/java-impl/resources/inspectionDescriptions/ComparatorMinMaxCanBeUsed.html index a39415edfdc4..26faeff9b50d 100644 --- a/java/java-impl/resources/inspectionDescriptions/ComparatorMinMaxCanBeUsed.html +++ b/java/java-impl/resources/inspectionDescriptions/ComparatorMinMaxCanBeUsed.html @@ -1,16 +1,20 @@ -Reports ternary expressions using Comparator.compare() that can be replaced -with Comparator.max() or Comparator.min() methods available since Java 26. +Reports if statements and ternary expressions with Comparator.compare() calls +that can be replaced with Comparator.max() or Comparator.min() calls. -

Example:

+

Example:


 Comparator<String> comp = Comparator.naturalOrder();
-/*before*/ String result = comp.compare(a, b) > 0 ? a : b;
-/*after*/  String result = comp.max(a, b);
+String result = comp.compare(a, b) > 0 ? a : b;
+
+

After the quick-fix is applied:

+

+Comparator<String> comp = Comparator.naturalOrder();
+String result = comp.max(a, b);
 
-

New in 2026.2

+

New in 2026.1

diff --git a/java/java-tests/testData/ig/com/siyeh/igtest/migration/comparator_min_max_can_be_used/ComparatorMinMaxCanBeUsed.after.java b/java/java-tests/testData/ig/com/siyeh/igtest/migration/comparator_min_max_can_be_used/ComparatorMinMaxCanBeUsed.after.java index 80ace89fa5e7..5860e275426b 100644 --- a/java/java-tests/testData/ig/com/siyeh/igtest/migration/comparator_min_max_can_be_used/ComparatorMinMaxCanBeUsed.after.java +++ b/java/java-tests/testData/ig/com/siyeh/igtest/migration/comparator_min_max_can_be_used/ComparatorMinMaxCanBeUsed.after.java @@ -4,13 +4,13 @@ import java.util.Comparator; class ComparatorMinMaxCanBeUsed { void testGreaterThan(Comparator comp, String a, String b) { - String r1 = comp.max(a, b); - String r2 = comp.min(a, b); + String r1 = comp.max(b, a); + String r2 = comp.min(b, a); } void testLessThan(Comparator comp, String a, String b) { - String r1 = comp.min(a, b); - String r2 = comp.max(a, b); + String r1 = comp.min(b, a); + String r2 = comp.max(b, a); } void testGreaterThanOrEqual(Comparator comp, String a, String b) { @@ -25,44 +25,44 @@ class ComparatorMinMaxCanBeUsed { void testReversedComparison(Comparator comp, String a, String b) { // 0 < compare(a, b) is equivalent to compare(a, b) > 0 - String r1 = comp.max(a, b); + String r1 = comp.max(b, a); // 0 >= compare(a, b) is equivalent to compare(a, b) <= 0 String r2 = comp.max(a, b); } void testParenthesized(Comparator comp, String a, String b) { - String r1 = comp.max(a, b); - String r2 = comp.min(a, b); + String r1 = comp.max(b, a); + String r2 = comp.min(b, a); } // If-statement patterns String testIfReturnGreaterThan(Comparator comp, String a, String b) { - return comp.max(a, b); + return comp.max(b, a); } String testIfReturnLessThan(Comparator comp, String a, String b) { - return comp.min(a, b); + return comp.min(b, a); } String testIfReturnReversedBranches(Comparator comp, String a, String b) { - return comp.min(a, b); + return comp.min(b, a); } String testIfReturnWithBlocks(Comparator comp, String a, String b) { - return comp.max(a, b); + return comp.max(b, a); } String testIfImplicitReturn(Comparator comp, String a, String b) { - return comp.max(a, b); + return comp.max(b, a); } void testIfAssignment(Comparator comp, String a, String b) { - String r = comp.max(a, b); + String r = comp.max(b, a); System.out.println(r); } void testIfOverwrittenDeclaration(Comparator comp, String a, String b) { - String r = comp.max(a, b); + String r = comp.max(b, a); System.out.println(r); } @@ -72,7 +72,7 @@ class ComparatorMinMaxCanBeUsed { } void testIfReversedComparison(Comparator comp, String a, String b) { - String r = comp.max(a, b); + String r = comp.max(b, a); System.out.println(r); } @@ -86,10 +86,15 @@ class ComparatorMinMaxCanBeUsed { if (comp.compare(a, b) == 0) r = a; else r = b; System.out.println(r); } + + void testWithPureCall(Comparator comp, String a, String b) { + // Side effects in compare arguments + String r1 = comp.max(b.trim(), a.trim()); + } void testNoWarning(Comparator comp, String a, String b) { // Side effects in compare arguments - String r1 = comp.max(a.trim(), b.trim()); + String r1 = comp.compare(process(a), process(b)) > 0 ? process(a) : process(b); // Non-matching branches String r2 = comp.compare(a, b) > 0 ? a : "default"; // Comparison to non-zero @@ -102,4 +107,6 @@ class ComparatorMinMaxCanBeUsed { // Branches swapped with unrelated expressions String r6 = comp.compare(a, b) > 0 ? b : b; } + + native String process(String s); } diff --git a/java/java-tests/testData/ig/com/siyeh/igtest/migration/comparator_min_max_can_be_used/ComparatorMinMaxCanBeUsed.java b/java/java-tests/testData/ig/com/siyeh/igtest/migration/comparator_min_max_can_be_used/ComparatorMinMaxCanBeUsed.java index f82b9cb01991..3ea67a2216b0 100644 --- a/java/java-tests/testData/ig/com/siyeh/igtest/migration/comparator_min_max_can_be_used/ComparatorMinMaxCanBeUsed.java +++ b/java/java-tests/testData/ig/com/siyeh/igtest/migration/comparator_min_max_can_be_used/ComparatorMinMaxCanBeUsed.java @@ -95,10 +95,15 @@ class ComparatorMinMaxCanBeUsed { if (comp.compare(a, b) == 0) r = a; else r = b; System.out.println(r); } + + void testWithPureCall(Comparator comp, String a, String b) { + // Side effects in compare arguments + String r1 = comp.compare(a.trim(), b.trim()) > 0 ? a.trim() : b.trim(); + } void testNoWarning(Comparator comp, String a, String b) { // Side effects in compare arguments - String r1 = comp.compare(a.trim(), b.trim()) > 0 ? a.trim() : b.trim(); + String r1 = comp.compare(process(a), process(b)) > 0 ? process(a) : process(b); // Non-matching branches String r2 = comp.compare(a, b) > 0 ? a : "default"; // Comparison to non-zero @@ -111,4 +116,6 @@ class ComparatorMinMaxCanBeUsed { // Branches swapped with unrelated expressions String r6 = comp.compare(a, b) > 0 ? b : b; } + + native String process(String s); }